Я работаю над приложением Rails, которое использует движок. Я использую инициализатор для настройки одного из контроллеров моего движка, чтобы он запускал действие в хост-приложении. Код выглядит примерно так:
# config/initializers/my_engine.rb
MyEngine::SomeController.after_filter proc {
# Do something in the host app
}, :only => :update
Это отлично работает в производственной среде, но в режиме разработки процедура вызывается только при первом запросе. Это связано с тем, что классы перезагружаются, и эта конфигурация теряется, потому что она была сохранена в переменной класса. (Например, MyEngine :: SomeController
перезагружается из файла, в котором он находится, и, поскольку after_filter
там не объявлен, он не добавляется обратно.)
В режиме разработки Rails использует следующую стратегию загрузки:
app
перезагружается при каждом запросе, при условии, что вы его активно изменяете. lib
вместе с файлами config / initializer
загружается один раз при загрузке приложения. Файлы инициализатора обычно используются для настройки гемов. В прошлом драгоценные камни в основном имели код в каталоге lib
, поэтому было достаточно запустить их конфигурацию один раз.
Однако движки Rails имеют код в каталоге app
: контроллеры, модели и т. Д. Эти файлы перезагружаются в режиме разработки при каждом запросе. Следовательно, конфигурация, подобная моему примеру выше, теряется.
Rails предоставляет config.to_prepare
специально для решения этой проблемы: он запускается один раз в производстве и по каждому запросу в разработке.
Например, у нас есть это в application.rb, который отлично работает:
config.to_prepare do
# set up class variables (after_filters, etc)
end
Однако, если мне нужно поместить конфигурацию всех моих движков в application.rb
, это лишает смысла config / initializers
для организации вещей.
Итак, для любой конфигурации классов в каталогах app
моих движков я хочу поместить этот код в файлы в папке config / initializers
.
Вот мои вопросы.
конфигурацию
в область видимости в файле инициализатора. Я думаю, это будет Rails.application.config
. Это правильно? to_prepare
? Боюсь, что при многократном вызове предыдущие блоки будут перезаписаны. Как упоминал @Frederick Cheung, Rails.application.config.to_prepare
действительно работает в файлах config / initializer
, и их можно использовать сколько угодно в различных файлах; каждый вызов добавляет свой блок в массив, поэтому ничего не перезаписывается.
Итак решение этой проблемы таково:
# config/initializers/my_engine.rb
Rails.application.config.to_prepare do
MyEngine::SomeController.after_filter proc {
# Do something in the host app
}, :only => :update
end
Одна вещь, которая все еще кажется странной: я ожидал, что блок to_prepare
будет вызываться при каждом запросе в режиме разработки, но вместо этого он, кажется, вызывается случайным образом каждый третий запрос или около того. Я добавил блок:
Rails.application.config.to_prepare do
Rails.logger.info "Running the prepare block!"
end
... перезапустил приложение и девять раз обновил страницу. Я видел сообщение только на 1-м, 5-м, 7-м и 9-м запросах. Я не уверен, что объясняет такое поведение, но оно объясняет, почему мой код без to_prepare
периодически работал в разработке.