-
-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
152 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# frozen_string_literal: true | ||
|
||
module Dry | ||
module System | ||
module Plugins | ||
# @api private | ||
class InjectorMixin < Module | ||
MODULE_SEPARATOR = "::" | ||
|
||
attr_reader :name | ||
|
||
def initialize(name: "Deps") | ||
@name = name | ||
end | ||
|
||
def extended(container) | ||
container.after(:configure, &method(:define_mixin)) | ||
end | ||
|
||
private | ||
|
||
def define_mixin(container) | ||
inflector = container.config.inflector | ||
|
||
name_parts = name.split(MODULE_SEPARATOR) | ||
|
||
if name_parts[0] == "" | ||
name_parts.delete_at(0) | ||
root_module = Object | ||
else | ||
root_module = container_parent_module(container) | ||
end | ||
|
||
mixin_parent_mod = define_parent_modules( | ||
root_module, | ||
name_parts, | ||
inflector | ||
) | ||
|
||
mixin_parent_mod.const_set( | ||
inflector.camelize(name_parts.last), | ||
container.injector | ||
) | ||
end | ||
|
||
def container_parent_module(container) | ||
if container.name | ||
parent_name = container.name.split(MODULE_SEPARATOR)[0..-2].join(MODULE_SEPARATOR) | ||
container.config.inflector.constantize(parent_name) | ||
else | ||
Object | ||
end | ||
end | ||
|
||
def define_parent_modules(parent_mod, name_parts, inflector) | ||
return parent_mod if name_parts.length == 1 | ||
|
||
name_parts[0..-2].reduce(parent_mod) { |parent_mod, mod_name| | ||
parent_mod.const_set(inflector.camelize(mod_name), Module.new) | ||
} | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe "Plugins / Injector mixin" do | ||
|
||
describe "default options" do | ||
it "creates a 'Deps' mixin in the container's parent module" do | ||
module Test | ||
class Container < Dry::System::Container | ||
use :injector_mixin | ||
configured! | ||
end | ||
end | ||
|
||
component = Object.new | ||
Test::Container.register "component", component | ||
|
||
depending_obj = Class.new do | ||
include Test::Deps["component"] | ||
end.new | ||
|
||
expect(depending_obj.component).to be component | ||
end | ||
end | ||
|
||
describe "name given" do | ||
it "creates a mixin with the given name in the container's parent module" do | ||
module Test | ||
class Container < Dry::System::Container | ||
use :injector_mixin, name: "Inject" | ||
configured! | ||
end | ||
end | ||
|
||
component = Object.new | ||
Test::Container.register "component", component | ||
|
||
depending_obj = Class.new do | ||
include Test::Inject["component"] | ||
end.new | ||
|
||
expect(depending_obj.component).to be component | ||
end | ||
end | ||
|
||
describe "nested name given" do | ||
it "creates a mixin with the given name in the container's parent module" do | ||
module Test | ||
class Container < Dry::System::Container | ||
use :injector_mixin, name: "Inject::These::Pls" | ||
configured! | ||
end | ||
end | ||
|
||
component = Object.new | ||
Test::Container.register "component", component | ||
|
||
depending_obj = Class.new do | ||
include Test::Inject::These::Pls["component"] | ||
end.new | ||
|
||
expect(depending_obj.component).to be component | ||
end | ||
end | ||
|
||
describe "top-level name given" do | ||
it "creates a mixin with the given name in the top-level module" do | ||
module Test | ||
class Container < Dry::System::Container | ||
use :injector_mixin, name: "::Deps" | ||
configured! | ||
end | ||
end | ||
|
||
component = Object.new | ||
Test::Container.register "component", component | ||
|
||
depending_obj = Class.new do | ||
include ::Deps["component"] | ||
end.new | ||
|
||
expect(depending_obj.component).to be component | ||
end | ||
end | ||
end |