-
Notifications
You must be signed in to change notification settings - Fork 34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
instance variables are overwritten with nil value when DSL and block contexts are same #29
Comments
Hi @taichi-ishitani firstly thank you for your bug report and pull request! Can you help me understand a little about what this issue means in the real world? The code you've described above, where you provide a custom DSLContext and then do a manual Basically, what real-world problem does this cause? |
I'm creating a configuration DSL class by using Docile gem. However my configuration DSL class does not work well because of this issue. # config_dsl.rb
require 'docile'
class ConfigDSL
def project_name(name = nil)
@project_name = name if name
@project_name
end
def data_width(width = nil)
@data_width = width if width
@data_width
end
def load_file(file)
block = binding.eval("proc { #{File.binread(file)} }", file)
Docile.dsl_eval(self, &block)
end
end
if $0 == __FILE__
dsl = ConfigDSL.new
dsl.load_file(ARGV[0])
p dsl.project_name, dsl.data_width
end In Here is a example config file and usage: # my_config.rb
project_name :my_project
data_width 64
After loading If you want more information, please let me know. |
Thank you so much @taichi-ishitani for such a clear problem description. Please give me just a moment to investigate this usage, to make sure I fully understand what is happening, and why the PR fixes it :) |
Ah ok. Is this understanding correct: Use case: DSL method sets instance variable on DSL object, and also the DSL object is the block's context My understanding is that this will only occur when the block's context is the same as the DSL object instance -- which is why we hadn't seen this before. Does that match your understanding? Or have I missed something? |
@taichi-ishitani I think my understanding is correct, because please observe that the following variation works as expected: # config_dsl.rb
require 'docile'
class ConfigDSL
def project_name(name = nil)
@project_name = name if name
@project_name
end
def data_width(width = nil)
@data_width = width if width
@data_width
end
def self.load_file(file)
block = binding.eval("proc { #{File.binread(file)} }", file)
Docile.dsl_eval(new, &block)
end
end
if $0 == __FILE__
dsl = ConfigDSL.load_file(ARGV[0])
p dsl.project_name, dsl.data_width
end What you see above is more similar to how Docile is often used in practice, which is probably why this hasn't come up before. The difference is that the block's context is NOT the same as the DSL object instance here. Does this make sense? Regardless, I will still accept your PR -- but knowing the above now, can you think about how to provide a clear RSpec example which covers this use case? |
@ms-ati
OK, I will create RSpec exmple for this issue tomorrow. |
Yes, please! :) Thank you |
I have added a RSpec example for this issue: b589c46 |
Thanks again @taichi-ishitani! This is merged. |
@ms-ati Thank you for merging my PR! |
Instance variables of DSL context object are overwritten with nil value when DSL conetext object and block context object are the same object.
Here is example code:
I think the result of above code should be like below:
but the actual result is below:
The text was updated successfully, but these errors were encountered: