Skip to content

Commit

Permalink
methods strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
maxhollmann committed Nov 20, 2020
1 parent 53b150d commit 29a9d10
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 19 deletions.
1 change: 1 addition & 0 deletions lib/dry/auto_inject/strategies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ def self.register_default(name, strategy)
require 'dry/auto_inject/strategies/args'
require 'dry/auto_inject/strategies/hash'
require 'dry/auto_inject/strategies/kwargs'
require 'dry/auto_inject/strategies/methods'
33 changes: 33 additions & 0 deletions lib/dry/auto_inject/strategies/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module Dry
module AutoInject
class Strategies
# @api private
class Base < Module
ClassMethods = Class.new(Module)
InstanceMethods = Class.new(Module)

attr_reader :container
attr_reader :dependency_map
attr_reader :instance_mod
attr_reader :class_mod

def initialize(container, *dependency_names)
@container = container
@dependency_map = DependencyMap.new(*dependency_names)
@instance_mod = InstanceMethods.new
@class_mod = ClassMethods.new
end

# @api private
def included(klass)
klass.send(:include, instance_mod)
klass.extend(class_mod)

super
end
end
end
end
end
21 changes: 2 additions & 19 deletions lib/dry/auto_inject/strategies/constructor.rb
Original file line number Diff line number Diff line change
@@ -1,36 +1,19 @@
# frozen_string_literal: true

require 'dry/auto_inject/strategies/base'
require 'dry/auto_inject/dependency_map'

module Dry
module AutoInject
class Strategies
class Constructor < Module
ClassMethods = Class.new(Module)
InstanceMethods = Class.new(Module)

attr_reader :container
attr_reader :dependency_map
attr_reader :instance_mod
attr_reader :class_mod

def initialize(container, *dependency_names)
@container = container
@dependency_map = DependencyMap.new(*dependency_names)
@instance_mod = InstanceMethods.new
@class_mod = ClassMethods.new
end

class Constructor < Base
# @api private
def included(klass)
define_readers

define_new
define_initialize(klass)

klass.send(:include, instance_mod)
klass.extend(class_mod)

super
end

Expand Down
59 changes: 59 additions & 0 deletions lib/dry/auto_inject/strategies/methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

require 'dry/auto_inject/strategies/base'
require 'dry/auto_inject/method_parameters'

module Dry
module AutoInject
class Strategies
# @api private
class Methods < Base
# @api private
def included(klass)
define_class_methods
define_instance_methods

super
end

private

def define_class_methods
class_mod.class_exec(container, dependency_map) do |container, dependency_map|
dependency_map.to_h.each do |name, identifier|
define_method name do
container[identifier]
end
end

def with_deps(**deps)
Class.new(self) do |klass|
deps.each do |name, value|
singleton_class.define_method name do
value
end
end
end
end
end

self
end

def define_instance_methods
instance_mod.class_exec(container, dependency_map) do |container, dependency_map|
dependency_map.to_h.each do |name, identifier|
define_method name do
self.class.send(name)
end
end
end

self
end
end

register :methods, Methods
end
end
end
26 changes: 26 additions & 0 deletions spec/integration/methods_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

require 'pry'

RSpec.describe 'methods' do
it 'defines methods returning dependencies' do
module Test
AutoInject = Dry::AutoInject(one: 'dep 1', two: 'dep 2').methods
end

obj = Class.new do
include Test::AutoInject[:one, :two]
end

expect(obj.one).to eq 'dep 1'
expect(obj.new.one).to eq 'dep 1'
expect(obj.two).to eq 'dep 2'
expect(obj.new.two).to eq 'dep 2'

other_obj = obj.with_deps(one: 'other dep 1')
expect(other_obj.one).to eq 'other dep 1'
expect(other_obj.new.one).to eq 'other dep 1'
expect(other_obj.two).to eq 'dep 2'
expect(other_obj.new.two).to eq 'dep 2'
end
end

0 comments on commit 29a9d10

Please sign in to comment.