Change the context/binding inside a block in ruby
Paste this code:
def evaluate(&block) @self_before_instance_eval = eval "self", block.binding instance_eval &block end def method_missing(method, *args, &block) @self_before_instance_eval.send method, *args, &block end
For more information, refer to this really good article here
Maybe
def command(*names, &blk) command = make_command_object(..) command.instance_eval(&blk)end
can evaluate the block in the context of command object.
class CommandDSL def self.call(&blk) # Create a new CommandDSL instance, and instance_eval the block to it instance = new instance.instance_eval(&blk) # Now return all of the set instance variables as a Hash instance.instance_variables.inject({}) { |result_hash, instance_variable| result_hash[instance_variable] = instance.instance_variable_get(instance_variable) result_hash # Gotta have the block return the result_hash } end def desc(str); @desc = str; end def switch(sym); @switch = sym; end def action(&blk); @action = blk; endenddef command(name, &blk) values_set_within_dsl = CommandDSL.call(&blk) # INSERT CODE HERE p name p values_set_within_dsl endcommand :list do desc 'show todos in long form' switch :l action do |global,option,args| # some code that's not relevant to this question endend
Will print:
:list{:@desc=>"show todos in long form", :@switch=>:l, :@action=>#<Proc:0x2392830@C:/Users/Ryguy/Desktop/tesdt.rb:38>}