【问题标题】:Ruby refinements with instance_eval使用 instance_eval 进行 Ruby 改进
【发布时间】:2016-03-22 03:05:20
【问题描述】:

我想对 DSL 进行一些改进。我可以使用此示例进行改进:

module ArrayExtras
  refine Array do
    def speak
      puts 'array!'
    end
  end
end

module MyUniverse
  using ArrayExtras
  class Thing
    def initialize
      [1].speak
    end
  end
end
MyUniverse::Thing.new

这会打印出“数组!”正好。但是一旦我引入instance_eval,方法就找不到了:

module MyUniverse
  using ArrayExtras
  class DSL
    def initialize(&block)
      instance_eval(&block)
    end
  end
end

MyUniverse::DSL.new do
  [1].speak
end

我得到了 [1] 的 undefined methodspeak':Array (NoMethodError)`

有没有办法在 instance_eval 中进行改进?

【问题讨论】:

    标签: ruby instance-eval refinements


    【解决方案1】:

    细化是词法范围的。您在错误的词汇上下文中激活了细化。您需要在调用精炼方法的地方激活它:

    module ArrayExtras
      refine Array do
        def speak
          puts 'array!'
        end
      end
    end
    
    module MyUniverse
      class DSL
        def initialize(&block)
          instance_eval(&block)
        end
      end
    end
    
    using ArrayExtras
    
    MyUniverse::DSL.new do
      [1].speak
    end
    # array!
    

    【讨论】:

    • 那么有没有办法让MyUniverse::DSL.new方法调用自包含呢? IE。不要求此方法的用户将using ... 行添加到他们的代码中。
    【解决方案2】:

    在某些情况下,您可以通过绑定上的using ArrayExtras 来实现。

    module MyUniverse
      using ArrayExtras
      class DSL
        def initialize(&block)
          block.binding.eval("using ArrayExtras")
          instance_eval(&block)
        end
      end
    end
    
    MyUniverse::DSL.new do
      [1].speak
    end
    

    这仅在您不在实例中使用您的类时才有效,它仅在 binding 是模块或类上下文时有效,否则 eval 将失败,因为 main.using is permitted only at toplevel

    【讨论】:

      【解决方案3】:

      如果你想提炼ruby核心BaseObject,你需要修改如下。

      module ArrayExtras
        refine ::Array do
          def speak
            puts 'array!'
         end
        end
      end
      

      它将在顶级类中找到。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-22
        • 2012-01-12
        • 2011-03-26
        • 2021-07-23
        相关资源
        最近更新 更多