Exclude certain methods from falling back from block context to dsl object
This appears to address the case where the identity of 'self' within the outer block of a nested DSL is appearing to be overwritten with the identity of inner DSL objects, as reported by @robkinyon. Fixes #31
This commit is contained in:
parent
0b355504e9
commit
67517e7573
|
@ -21,6 +21,10 @@ module Docile
|
||||||
:instance_variable_get, :instance_variable_set,
|
:instance_variable_get, :instance_variable_set,
|
||||||
:remove_instance_variable]
|
:remove_instance_variable]
|
||||||
|
|
||||||
|
# The set of methods which will **not** fallback from the block's context
|
||||||
|
# to the dsl object.
|
||||||
|
NON_FALLBACK_METHODS = Set[:class, :self, :respond_to?, :instance_of?]
|
||||||
|
|
||||||
# The set of instance variables which are local to this object and hidden.
|
# The set of instance variables which are local to this object and hidden.
|
||||||
# All other instance variables will be copied in and out of this object
|
# All other instance variables will be copied in and out of this object
|
||||||
# from the scope in which this proxy was created.
|
# from the scope in which this proxy was created.
|
||||||
|
@ -49,7 +53,8 @@ module Docile
|
||||||
# contain calls to methods on the DSL object.
|
# contain calls to methods on the DSL object.
|
||||||
singleton_class.
|
singleton_class.
|
||||||
send(:define_method, :method_missing) do |method, *args, &block|
|
send(:define_method, :method_missing) do |method, *args, &block|
|
||||||
if receiver.respond_to?(method.to_sym)
|
m = method.to_sym
|
||||||
|
if !NON_FALLBACK_METHODS.include?(m) && receiver.respond_to?(m)
|
||||||
receiver.__send__(method.to_sym, *args, &block)
|
receiver.__send__(method.to_sym, *args, &block)
|
||||||
else
|
else
|
||||||
super(method, *args, &block)
|
super(method, *args, &block)
|
||||||
|
|
|
@ -283,6 +283,37 @@ describe Docile do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "identity of 'self' inside nested dsl blocks" do
|
||||||
|
# see https://github.com/ms-ati/docile/issues/31
|
||||||
|
subject do
|
||||||
|
identified_selves = {}
|
||||||
|
|
||||||
|
outer do
|
||||||
|
identified_selves[:a] = self
|
||||||
|
|
||||||
|
inner do
|
||||||
|
identified_selves[:b] = self
|
||||||
|
end
|
||||||
|
|
||||||
|
identified_selves[:c] = self
|
||||||
|
end
|
||||||
|
|
||||||
|
identified_selves
|
||||||
|
end
|
||||||
|
|
||||||
|
it "identifies self inside outer dsl block" do
|
||||||
|
expect(subject[:a]).to be_instance_of(OuterDSL)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "replaces self inside inner dsl block" do
|
||||||
|
expect(subject[:b]).to be_instance_of(InnerDSL)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "restores self to the outer dsl object after the inner dsl block" do
|
||||||
|
expect(subject[:c]).to be_instance_of(OuterDSL)
|
||||||
|
expect(subject[:c]).to be(subject[:a])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when DSL context object is a Dispatch pattern" do
|
context "when DSL context object is a Dispatch pattern" do
|
||||||
|
|
Loading…
Reference in New Issue