Как я могу запустить НЕКОТОРЫЕ инициализаторы при выполнении ресурсов Rails: прекомпиляция? - PullRequest
17 голосов
/ 11 февраля 2012

Справочная информация

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

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

Ответы [ 5 ]

45 голосов
/ 03 октября 2012

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

# 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, поскольку он будет работать только в активахgroup.

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

7 голосов
/ 07 марта 2012

Определенно проверьте asset_sync на github.Или в нашей статье, посвященной центру разработки Heroku Использование ресурса CDN Host с Rails 3.1 в Heroku .

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

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

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

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

<% 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, и делает это только один раз (что позволяет избежать постоянных проблем с переопределением).

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

1 голос
/ 11 февраля 2012

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

0 голосов
/ 11 февраля 2012

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

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

...