Skip to content

Commit

Permalink
Add InstanceDSL to isolate #initialize method from mixin
Browse files Browse the repository at this point in the history
  • Loading branch information
nepalez committed Apr 5, 2017
1 parent 1325f6c commit 92d9e19
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 28 deletions.
1 change: 1 addition & 0 deletions .rspec
@@ -1,3 +1,4 @@
--format documentation
--color
--require spec_helper
--warnings
11 changes: 4 additions & 7 deletions lib/dry/initializer.rb
Expand Up @@ -8,7 +8,8 @@ module Initializer
require_relative "initializer/param"
require_relative "initializer/option"
require_relative "initializer/builder"
require_relative "initializer/dsl"
require_relative "initializer/instance_dsl"
require_relative "initializer/class_dsl"

# rubocop: disable Style/ConstantName
Mixin = self # for compatibility to versions below 0.12
Expand All @@ -18,7 +19,7 @@ module Initializer
obj.define_singleton_method(:inspect) { "Dry::Initializer::UNDEFINED" }
end.freeze

extend Dry::Initializer::DSL
extend Dry::Initializer::ClassDSL

def param(*args)
__initializer_builder__.param(*args).call(__initializer_mixin__)
Expand All @@ -31,11 +32,7 @@ def option(*args)
private

def __initializer_mixin__
@__initializer_mixin__ ||= Module.new do
def initialize(*args)
__initialize__(*args)
end
end
@__initializer_mixin__ ||= Module.new
end

def __initializer_builder__(**settings)
Expand Down
19 changes: 6 additions & 13 deletions lib/dry/initializer/dsl.rb → lib/dry/initializer/class_dsl.rb
@@ -1,22 +1,17 @@
module Dry::Initializer
module DSL
module ClassDSL
attr_reader :config

def [](**settings)
Module.new do
extend Dry::Initializer::DSL
extend Dry::Initializer::ClassDSL
include Dry::Initializer
@config = settings
end
end

def define(fn = nil, &block)
mixin = Module.new do
def initialize(*args)
__initialize__(*args)
end
end

mixin = Module.new { include InstanceDSL }
builder = Builder.new Hash(config)
builder.instance_exec(&(fn || block))
builder.call(mixin)
Expand All @@ -29,12 +24,10 @@ def extended(klass)
super
mixin = klass.send(:__initializer_mixin__)
builder = klass.send(:__initializer_builder__, Hash(config))

builder.call(mixin)
klass.include(mixin)
klass.send(:define_method, :initialize) do |*args|
__initialize__(*args)
end

klass.include(InstanceDSL) # defines #initialize
klass.include(mixin) # defines #__initialize__ (to be redefined)
end

def mixin(fn = nil, &block)
Expand Down
15 changes: 15 additions & 0 deletions lib/dry/initializer/instance_dsl.rb
@@ -0,0 +1,15 @@
module Dry::Initializer
module InstanceDSL
private

# The method is reloaded explicitly
# in a class that extend [Dry::Initializer], or in its subclasses.
def initialize(*args)
__initialize__(*args)
end

# The method is redefined implicitly every time
# a `param` or `option` is invoked.
def __initialize__(*); end
end
end
16 changes: 8 additions & 8 deletions spec/definition_spec.rb
Expand Up @@ -2,13 +2,13 @@
shared_examples :initializer do |in_context|
subject { Test::Foo.new(1, bar: 2) }

it "sets variables when defined by #{in_context}" do
it "sets variables when defined via `#{in_context}`" do
expect(subject.instance_variable_get(:@foo)).to eql 1
expect(subject.instance_variable_get(:@bar)).to eql 2
end
end

it_behaves_like :initializer, "extending Dry::Initializer" do
it_behaves_like :initializer, "extend Dry::Initializer" do
before do
class Test::Foo
extend Dry::Initializer
Expand All @@ -18,7 +18,7 @@ class Test::Foo
end
end

it_behaves_like :initializer, "extending Dry::Initializer::Mixin" do
it_behaves_like :initializer, "extend Dry::Initializer::Mixin" do
before do
class Test::Foo
extend Dry::Initializer::Mixin
Expand All @@ -28,7 +28,7 @@ class Test::Foo
end
end

it_behaves_like :initializer, "extending Dry::Initializer[undefined: false]" do
it_behaves_like :initializer, "extend Dry::Initializer[undefined: false]" do
before do
class Test::Foo
extend Dry::Initializer[undefined: false]
Expand All @@ -38,7 +38,7 @@ class Test::Foo
end
end

it_behaves_like :initializer, "including Dry::Initializer with block" do
it_behaves_like :initializer, "include Dry::Initializer with block" do
before do
class Test::Foo
include Dry::Initializer.define {
Expand All @@ -49,7 +49,7 @@ class Test::Foo
end
end

it_behaves_like :initializer, "including Dry::Initializer with lambda" do
it_behaves_like :initializer, "include Dry::Initializer with lambda" do
before do
class Test::Foo
include Dry::Initializer.define -> do
Expand All @@ -60,7 +60,7 @@ class Test::Foo
end
end

it_behaves_like :initializer, "including Dry::Initializer[undefined: false]" do
it_behaves_like :initializer, "include Dry::Initializer[undefined: false]" do
before do
class Test::Foo
include Dry::Initializer[undefined: false].define {
Expand All @@ -71,7 +71,7 @@ class Test::Foo
end
end

it_behaves_like :initializer, "including Dry::Initializer::Mixin" do
it_behaves_like :initializer, "include Dry::Initializer::Mixin" do
before do
class Test::Foo
include Dry::Initializer::Mixin.define {
Expand Down

0 comments on commit 92d9e19

Please sign in to comment.