Что означает этот код Rails Engine: config.to_prepare &method(:activate).to_proc

Я работаю со Spree, которая активно использует движки Rails. Обычный шаблон, который я нахожу, таков. Однако у меня проблемы с пониманием этого кода.

class Engine < Rails::Engine 
  def self.activate
    ...
  end     

  config.to_prepare &method(:activate).to_proc
end
  1. Что делает .to_prepare
  2. Что делает оператор &method?
  3. Каков общий эффект кода?

Огромное спасибо!


person Jack Kinsella    schedule 24.02.2011    source источник


Ответы (1)


&method(:activate).to_proc

Лучше всего потреблять по одному предмету за раз. (Следует отметить, что эта часть кода на 100% не-Rails-специфичная для Ruby.)

method - это метод Ruby (все это очень мета). Это задокументировано следующим образом:

Ищет именованный метод как приемник в obj, возвращая объект Method (или вызывая NameError). Объект Method действует как замыкание в экземпляре объекта obj, поэтому переменные экземпляра и значение self остаются доступными.

Посмотрите следующую сессию IRB:

ruby-1.9.2-p136 :001 > def my_method
ruby-1.9.2-p136 :002?>   puts "in my_method"
ruby-1.9.2-p136 :003?>   10
ruby-1.9.2-p136 :004?>   end
 => nil 
ruby-1.9.2-p136 :005 > method(:my_method)
 => #<Method: Object#my_method>

Таким образом, вызов method ищет (в вашем примере) метод activate и создает Method объект. для этого. Method содержит метод to_proc, который "возвращает объект Proc, соответствующий этому методу" . Продолжаем нашу сессию IRB:

ruby-1.9.2-p136 :006 > method(:my_method).to_proc
 => #<Proc:0x000001010a3e38 (lambda)>

Наконец, мы используем оператор амперсанда, который, если он предшествует объекту Proc во время вызова метода, будет заменен блоком, который содержит Proc. Еще раз в IRB:

ruby-1.9.2-p136 :007 > def executor(&block)
ruby-1.9.2-p136 :008?>   block.call
ruby-1.9.2-p136 :009?>   end
 => nil 
ruby-1.9.2-p136 :010 > executor( &method(:my_method).to_proc )
in my_method
 => 10

Итак, в псевдокоде указанная вами строка говорит:

config.to_prepare(a block containing the functionality of the method activate)

config.to_prepare

[Отредактировано на основе комментария Шофа]

config.to_prepare берет блок, который нужно запустить для настройки вашего Railtie/Engine. Он запускается один раз в производственном режиме и при каждом запросе в режиме разработки, и это единственный код, который гарантированно вызывается при каждом отдельном запросе в режиме разработки. Это важно, если вы изменяете классы (class_eval и т. д.) как часть инициализации вашего движка; в противном случае вы увидите различное поведение в разработке и производстве.

Но почему?

Причина, по которой это распространенная идиома, заключается в том, что вам не нужно определять код подготовки внутри самого блока to_prepare; вы можете определить метод(ы) в своем классе, а затем преобразовать их в блок (который запоминает свою область действия), используя магию, описанную выше. Код функционально эквивалентен:

class Engine < Rails::Engine 
  config.to_prepare do
    (the contents of self.activate)
  end
end
person Michelle Tilley    schedule 24.02.2011
comment
Отличный ответ. Просто хотел добавить, что материал config.to_prepare — это единственное, что гарантированно вызывается при каждом отдельном запросе в режиме разработки. Это важно, если вы изменяете классы (class_eval и т. д.) как часть инициализации вашего движка. В противном случае вы увидите различное поведение в разработке и производстве. - person Sean Schofield; 28.02.2011