Skip to content

Commit

Permalink
Add injector mixin plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
timriley committed Jan 31, 2022
1 parent 5fa528d commit d973260
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/dry/system/plugins.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ def enabled_plugins

require "dry/system/plugins/zeitwerk"
register(:zeitwerk, Plugins::Zeitwerk)

require_relative "plugins/injector_mixin"
register(:injector_mixin, Plugins::InjectorMixin)
end
end
end
65 changes: 65 additions & 0 deletions lib/dry/system/plugins/injector_mixin.rb
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
84 changes: 84 additions & 0 deletions spec/integration/container/plugins/injector_mixin_spec.rb
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

0 comments on commit d973260

Please sign in to comment.