Change the context/binding inside a block in ruby

前端 未结 4 1519
盖世英雄少女心
盖世英雄少女心 2020-12-13 04:27

I have a DSL in Ruby that works like so:

desc \'list all todos\'
command :list do |c|
  c.desc \'show todos in long form\'
  c.switch :l
  c.action do |globa         


        
相关标签:
4条回答
  • 2020-12-13 04:57

    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

    0 讨论(0)
  • 2020-12-13 04:58
    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; end
    end
    
    def command(name, &blk)
      values_set_within_dsl = CommandDSL.call(&blk)
    
      # INSERT CODE HERE
      p name
      p values_set_within_dsl 
    end
    
    command :list do
      desc 'show todos in long form'
      switch :l
      action do |global,option,args|
        # some code that's not relevant to this question
      end
    end
    

    Will print:

    :list
    {:@desc=>"show todos in long form", :@switch=>:l, :@action=>#<Proc:0x2392830@C:/Users/Ryguy/Desktop/tesdt.rb:38>}
    
    0 讨论(0)
  • 2020-12-13 05:17

    Maybe

    def command(*names, &blk)
      command = make_command_object(..)
      command.instance_eval(&blk)
    end
    

    can evaluate the block in the context of command object.

    0 讨论(0)
  • 2020-12-13 05:17

    I wrote a class that handles this exact issue, and deals with things like @instance_variable access, nesting, and so forth. Here's the write-up from another question:

    Block call in Ruby on Rails

    0 讨论(0)
提交回复
热议问题