Как я могу предотвратить потерю конфигурации инициализатора в режиме разработки?
Я работаю над приложением Rails, которое использует движок. Я использую инициализатор для настройки одного из контроллеров моего движка, чтобы он вызывал действие в главном приложении. Код выглядит примерно так:
# config/initializers/my_engine.rb
MyEngine::SomeController.after_filter proc {
# Do something in the host app
}, :only => :update
Это хорошо работает в производственной среде, но в режиме разработки proc вызывается только при первом запросе. Это потому, что классы перезагружаются, и эта конфигурация теряется, потому что она была сохранена в переменной класса. (Например,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
.
Вот мои вопросы.
Мне непонятно как получитьconfig
в область действия в файле инициализатора. Я думаю, что это будет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
работал с перерывами в разработке.