使用instance_eval进行Ruby优化

时间:2015-12-16 04:57:54

标签: ruby instance-eval refinements

我想为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 method说话:数组(NoMethodError)`

有没有办法让实现在instance_eval中进行优化?

3 个答案:

答案 0 :(得分:2)

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

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!

答案 1 :(得分:1)

在某些情况下,您可以通过绑定上的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将失败,因为{{1} }。

答案 2 :(得分:-1)

如果要优化ruby核心BaseObject,则需要按以下方式对其进行修改。

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

它将在顶级课程中找到。