Работает ли `define_method` при каждом создании класса? - PullRequest
0 голосов
/ 15 мая 2019

Когда мой класс динамически создает несколько удобных методов, например:

class MyClass < ActiveRecord::Base
  ...
  %w(foo bar baz).freeze.each do |part_one|
    %w(alpha beta gamma).freeze.each do |part_two|
      define_method "#{part_one}_#{part_two}" do
        lookup_stuff(part_one, part_two)
      end
    end
  end
  ...
end

Итерация и создание метода происходят для каждого экземпляра класса или только один раз, когда класс анализируется впервые и создается объект модели для этого класса?

У меня есть догадка, что это произойдет только один раз, но я не могу найти ничего в документации, подтверждающей это.

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Методы в Ruby всегда определяются в модулях (или классах, которые являются модулем определенного типа), а не в экземплярах.Хотя, очевидно, можно определить метод для экземпляра, например,

class Foo; end
foo = Foo.new
def foo.quux
  puts "QUUX"
end
foo.quux # => QUUX
bar = Foo.new
bar.quux # => QUUX

, на самом деле метод помещает метод в так называемый одноэлементный класс foo, который происходит от Foo.В Ruby не определены методы для экземпляров.Когда кто-то вызывает метод, он просматривает цепочку наследования.

Ваш define_method заполнит self.class методами во время его выполнения;любые экземпляры self.class или его потомки будут иметь к ним доступ с тех пор.

0 голосов
/ 15 мая 2019

Обычно этот код оценивается один раз и только тогда, когда часть определения класса , как в:

class Example
  # Code here is executed immediately in the order the statements appear
  %w[ foo bar baz ].each do |...|
  end

  def example
    # Code here is only run if this method is executed, and only when
    # the method is executed.
  end
end

Вы можете узнать с помощью «отладки printf»:

class Example
  puts "Am I being run once or a whole bunch of times?"

  %w[ foo bar baz ].each do |...|
  end
end

Где это теперь будет выводить диагностический вывод, который вы можете использовать.

Исключением из этого является среда автозагрузчика Ruby on Rails для разработки, где вещи в app/ будут загружаться один раз для запроса, а не для процесса.

...