如何将变量拉入单例类的范围?

时间:2011-05-27 18:57:35

标签: ruby metaprogramming

module EventSubscriber
  def method_missing(method_name, *args)
    if method_name[/^subscribe_to_(.*)/]
      class << self
        define_method(method_name) do |*arguments|
            # ....
        end
      end

      send(method_name, *args)
    else
      super
    end
  end
end

EventSubscriber是一个混合到类中以订阅事件的模块。如果调用了一个名为subscribe_to_*的方法,则会定义它(以避免再次出现method_missing开销)然后调用。如何将该变量纳入范围?

问题出在单例类中,method_name似乎无法访问。 Ruby抱怨“未定义的局部变量或方法”。

我知道我可以使用self.class.send(:define_method ..)来做到这一点,但除非必须,否则我宁愿不这样做。我更喜欢这种格式。

2 个答案:

答案 0 :(得分:1)

如何使用:

module EventSubscriber
  extend self 

  def method_missing(method_name, *args)
    if method_name[/^subscribe_to_(.*)/]
      class << self
        define_method(method_name) do |*arguments|
          # ....
        end
      end

      send(method_name, *args)
    else
      super
    end
  end

  def singleton(obj)
    class << obj; self; end
  end

end

答案 1 :(得分:0)

您当前的问题是您使用class << object语法访问单例类并尝试访问method_name变量。任何class语句都会改变范围;因此,method_name如果没有在那里定义则不存在。

我仍然不确定你究竟想要完成什么,但这是我尝试解决你的问题:

module EventSubscriber
  def method_missing(method_name, *args)
    if method_name =~ /^subscribe_to_(.+)/
      class << self
        self
      end.define_method(method_name) do |*arguments|
        # ....
      end
      send method_name, *args
    else
      super
    end
  end
end

请注意,我还将正则表达式更改为更易于阅读的内容。