From d6216c4915f2e5a246d50125740b8b4e20f9f4e0 Mon Sep 17 00:00:00 2001 From: Max Hollmann Date: Wed, 22 Apr 2020 16:38:14 +0200 Subject: [PATCH] methods strategy --- lib/dry/auto_inject/strategies.rb | 1 + lib/dry/auto_inject/strategies/base.rb | 33 +++++++++++ lib/dry/auto_inject/strategies/constructor.rb | 21 +------ lib/dry/auto_inject/strategies/methods.rb | 59 +++++++++++++++++++ spec/integration/methods_spec.rb | 24 ++++++++ 5 files changed, 119 insertions(+), 19 deletions(-) create mode 100644 lib/dry/auto_inject/strategies/base.rb create mode 100644 lib/dry/auto_inject/strategies/methods.rb create mode 100644 spec/integration/methods_spec.rb diff --git a/lib/dry/auto_inject/strategies.rb b/lib/dry/auto_inject/strategies.rb index fd30e2e..a66266b 100644 --- a/lib/dry/auto_inject/strategies.rb +++ b/lib/dry/auto_inject/strategies.rb @@ -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' diff --git a/lib/dry/auto_inject/strategies/base.rb b/lib/dry/auto_inject/strategies/base.rb new file mode 100644 index 0000000..0306135 --- /dev/null +++ b/lib/dry/auto_inject/strategies/base.rb @@ -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 diff --git a/lib/dry/auto_inject/strategies/constructor.rb b/lib/dry/auto_inject/strategies/constructor.rb index 30e7a98..312e206 100644 --- a/lib/dry/auto_inject/strategies/constructor.rb +++ b/lib/dry/auto_inject/strategies/constructor.rb @@ -1,26 +1,12 @@ # 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 @@ -28,9 +14,6 @@ def included(klass) define_new define_initialize(klass) - klass.send(:include, instance_mod) - klass.extend(class_mod) - super end diff --git a/lib/dry/auto_inject/strategies/methods.rb b/lib/dry/auto_inject/strategies/methods.rb new file mode 100644 index 0000000..92db8c0 --- /dev/null +++ b/lib/dry/auto_inject/strategies/methods.rb @@ -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 diff --git a/spec/integration/methods_spec.rb b/spec/integration/methods_spec.rb new file mode 100644 index 0000000..d0ea776 --- /dev/null +++ b/spec/integration/methods_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +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