Подтвердить что ты не робот

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

Фон

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

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

Я сохраняю конкретную конфигурацию приложения в файле 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, встроенный в стек кедра. Когда вы нажимаете приложение в Heroku, он автоматически вызывает rake assets:precompile на сервере в качестве шага в процессе развертывания. Однако он делает это в изолированной среде без доступа к базе данных или нормальных ENV-vars.

Если приложению разрешено нормально инициализировать во время предварительной компиляции актива, возникает ошибка, связанная с подключением к базе данных. Это легко решить, добавив следующее в файл application.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:: Application.initialize!

4b9b3361

Ответ 1

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) и при предварительной компиляции без инициализации (из-за вышеприведенного кода).

Ответ 2

Определенно проверьте asset_sync на github. Или наша статья Heroku dev center на Использование ресурса CDN Host с Rails 3.1 на Heroku.

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

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

  • С активами_sync и S3 вы можете предварительно скомпилировать активы, означающие, что все активы готовы к немедленному обслуживанию на хосте /CDN актива.
  • Вам может потребоваться только пакет : активы в приложении .rb для прекомпиляции, сохранение памяти в процессе производства
  • Серверы приложений НИКОГДА не попадают на запросы актива. Знаете, вы можете потратить дорогое время на вычисление. Вычислительный.
  • Наилучшая практика HTTP-заголовки кэша установлены по умолчанию.
  • Вы можете включить автоматическое сжатие gzip с помощью одной дополнительной конфигурации

Ответ 3

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

<% 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, но во много раз лучше, чем встраивание конфигураций в файлы активов.

Ответ 4

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

Ответ 5

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

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