Ruby class_eval和yield

时间:2010-01-11 03:55:34

标签: ruby

伙计,我今天剥了洋葱的层,无论如何这里是代码

class MyClass
  def initialize(dynamic_methods)
    @arr = Array.new(dynamic_methods)
    @arr.each { |m|
      self.class.class_eval do
        define_method(m) do
          "<#{yield self if block_given?}>" 
        end
      end
    }
    end
end

tmp = MyClass.new ['method1', 'method2', 'method3']
tmp.method1 do |t|
  "here"
end

我的问题是,我正在尝试在执行方法时访问define_method(m)中的“here”,而不是在创建时。当前声明“&lt;#{yield self if block_given?}&gt;”不给我这个。如果您想知道,我必须按原样保留这部分代码,但我可以对MyClass进行所有我希望的更改。

tmp = MyClass.new ['method1', 'method2', 'method3']
tmp.method1 do |t|
  "here"
end

任何人都可以帮助解决语法问题吗?在此先感谢您的帮助。

更新:请参阅下面的回答。

2 个答案:

答案 0 :(得分:1)

尝试替换

define_method(m) do
  "<#{yield self if block_given?}>" 
end

使用:

define_method(m) do |&block|
  "<#{block.call if block}>" 
end

这适用于1.8.7及更高版本。您也可以尝试使用module_eval

self.class.module_eval %Q{
  def #{m}(&block)
    "<\#{block.call if block}>"
  end
}

答案 1 :(得分:0)

有很多来自谢尔盖的反馈和我自己的一些修修补补,我设法让它运作

class MyClass
  def initialize(dynamic_methods)
    @arr = Array.new(dynamic_methods)
    @arr.each { |m|
      self.class.module_eval %Q{
        def #{m}(&block)
          yield(self) if block_given?
        end
      end
    }
    end
end

tmp = MyClass.new ['method1', 'method2', 'method3']
tmp.method1 do |t|
  "here"
end

正如你所知,对谢尔盖的建议有一些小的调整,谢谢你所有的帮助谢尔盖。