Как я могу предотвратить потерю конфигурации инициализатора в режиме разработки?

Я работаю над приложением Rails, которое использует движок. Я использую инициализатор для настройки одного из контроллеров моего движка, чтобы он запускал действие в хост-приложении. Код выглядит примерно так:

# config/initializers/my_engine.rb
MyEngine::SomeController.after_filter proc {
  # Do something in the host app
}, :only => :update

Это отлично работает в производственной среде, но в режиме разработки процедура вызывается только при первом запросе. Это связано с тем, что классы перезагружаются, и эта конфигурация теряется, потому что она была сохранена в переменной класса. (Например, MyEngine :: SomeController перезагружается из файла, в котором он находится, и, поскольку after_filter там не объявлен, он не добавляется обратно.)

Некоторая предыстория Rails

В режиме разработки Rails использует следующую стратегию загрузки:

  • Код в каталоге app перезагружается при каждом запросе, при условии, что вы его активно изменяете.
  • Код в каталоге lib вместе с файлами config / initializer загружается один раз при загрузке приложения.

Файлы инициализатора обычно используются для настройки гемов. В прошлом драгоценные камни в основном имели код в каталоге lib , поэтому было достаточно запустить их конфигурацию один раз.

Как движки меняют ситуацию

Однако движки Rails имеют код в каталоге app : контроллеры, модели и т. Д. Эти файлы перезагружаются в режиме разработки при каждом запросе. Следовательно, конфигурация, подобная моему примеру выше, теряется.

Введите to_prepare

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 периодически работал в разработке.

19
задан Nathan Long 17 January 2012 в 16:29
поделиться