Как вытащить переменную в область действия синглтон-класса? - PullRequest
0 голосов
/ 27 мая 2011
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), а затем вызывается. Как я могу перенести эту переменную в область видимости?

Проблема внутри класса singleton, method_name, кажется, не доступен. Ruby жалуется на «неопределенную локальную переменную или метод».

Я знаю, что мог бы сделать это, используя self.class.send(:define_method ..), но я бы предпочел не делать этого, если мне не придется Я предпочитаю этот формат.

Ответы [ 2 ]

1 голос
/ 28 мая 2011

Как насчет использования:

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
0 голосов
/ 01 июня 2011

Ваша текущая проблема заключается в том, что вы используете синтаксис 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

Обратите внимание, что я также изменил регулярное выражение на что-то более простое для чтения.

...