Как я могу запустить некоторые инициализаторы при выполнении Rails assets: precompile?

фон

у меня есть приложение, которое я недавно обновил до Rails 3.2.1 (от рельсы 3.0.x) и переработали активы JS и CSS, чтобы использовать новый конвейер активов. Приложение размещено на Heroku с кедровым стеком Celadon.

Конфигурации Приложения

Я сохраняю конфигурацию приложения в файле YAML под названием app_config.yml и загрузите его в глобальную переменную APP_CONFIG с помощью инициализатора:

# config/initializers/load_app_config.rb

app_config_contents = YAML.load_file("#{Rails.root.to_s}/config/app_config.yml")
app_config_contents["default"] ||= {}
APP_CONFIG = app_config_contents["default"].merge(
                       app_config_contents[Rails.env] || {} ).symbolize_keys

компиляция активов на В Heroku

Heroku поддерживает трубопровод Rails asset, встроенный в Кедровый стек. Когда вы нажимаете приложение на Heroku, оно автоматически вызывает rake assets:precompile на сервере в качестве шага в процессе развертывания. Однако он делает это в изолированной среде без доступа к базе данных или обычных env vars.

если приложению разрешено инициализировать нормально во время предварительной компиляции активов, возникает ошибка при попытке подключения к базе данных. Это легко решается путем добавления следующее приложение.файл rb:

    # Do not load entire app when precompiling assets
    config.assets.initialize_on_precompile = false


Моя Проблема

, когда initialize_on_precompile = false установлено, ни один из инициализаторов в config/initializers/* бежать. Проблема, с которой я сталкиваюсь, заключается в том, что мне нужно, чтобы переменная APP_CONFIG была доступна во время предварительной компиляции активов.

как я могу получить load_app_config.rb для загрузки во время компиляции активов без инициализации всего приложения? Могу ли я что-то сделать с group параметр передан Rails-приложение.инициализировать! ?

5 ответов


Rails позволяет регистрировать инициализаторы только в определенных группах, но вам нужно использовать API Railtie:

# in config/application.rb

module AssetsInitializers
  class Railtie < Rails::Railtie
    initializer "assets_initializers.initialize_rails",
                :group => :assets do |app|
      require "#{Rails.root}/config/initializers/load_config.rb"
    end
  end
end

вам не нужно проверять, определен ли AppConfig, так как это будет выполняться только в группе активов.

и вы можете (и должны) продолжать использовать initialize_on_precompile = false. В load_config.инициализатор rb будет запущен при инициализации приложения (так как он находится в config/initializers) и при предварительной компиляции без инициализации (из-за указанного выше кодекса).


обязательно проверить asset_sync на github. Или наша статья Heroku dev centre на использование CDN asset Host с Rails 3.1 на Heroku.

проблемы с переменные среды недавно были решены плагином Heroku labs, что делает ваше приложение heroku config переменные доступны во время компиляции. Для этого прочитайте о user_env_compile плагин.

тоже. Существует довольно большой повышение производительности при использовании asset_sync vs позволяет приложению лениво компилировать активы в производстве или обслуживать их, предварительно скомпилированные непосредственно с серверов приложений. Однако я бы так сказал. Я его написал.

  • С asset_sync и S3 вы можете предварительно скомпилировать активы, означающие, что все активы там готовы быть поданы на хосте активов / CDN немедленно
  • вы можете требовать только активы bundle в приложении.РБ о прекомпиляции, сохранение памяти в производстве
  • ваши серверы приложений никогда не попадают для запросов активов. Знаешь, на это можно потратить много времени. Вычисления.
  • лучшие заголовки кэша HTTP практики установлены по умолчанию
  • вы можете включить автоматическое сжатие gzip с одной дополнительной конфигурации

вот что я придумал. В активах, которые нуждаются в конфигурации приложения, я помещаю эту строку в самом начале:

<% require "#{Rails.root}/config/initializers/load_config.rb" unless defined?(AppConfig) %>

... и добавить .erb к имени файла, так что video_player.js.coffee становится video_player.js.coffee.erb. Тогда я могу безопасно использовать AppConfig['somekey'] далее.

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

Да, это kludge, но много раз лучше, чем встраивание конфигураций в файлы активов.


для Heroku я запускаю Asset Sync gem для хранения моих файлов на CDN, чтобы избежать попадания Heroku для статических изображений. Это прекрасно работает. У меня также есть initialize на precompile false, но синхронизация активов запускает собственный инициализатор, чтобы вы могли поместить свой код в него. https://github.com/rumblelabs/asset_sync


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

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