在执行Rails资产时如何运行某些初始化程序:预编译?

时间:2012-02-10 21:48:23

标签: ruby-on-rails-3 ruby-on-rails-3.1 heroku asset-pipeline ruby-on-rails-3.2

背景

我有一个应用程序,我最近更新到Rails 3.2.1(来自Rails 3.0.x)并重构了JS和CSS资产以利用新的资产管道。该应用程序使用Celadon Cedar堆栈托管在Heroku上。

App Config

我将特定于应用程序的配置保存在名为app_config.yml的YAML文件中,并使用初始化程序将其加载到全局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支持内置于Cedar堆栈的Rails资产管道。当您将应用程序推送到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?我可以使用传递给Rails :: Application.initialize的group参数做些什么! ?

5 个答案:

答案 0 :(得分:45)

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是否已定义,因为它只会在资产组中运行。

您可以(并且应该)继续使用initialize_on_precompile = false。 load_config.rb初始化程序将在初始化应用程序时运行(因为它位于config/initializers,而不进行初始化时进行预编译(由于上述代码)。

答案 1 :(得分:7)

绝对可以在github上查看 asset_sync 。或者我们的Heroku开发中心文章Using a CDN asset Host with Rails 3.1 on Heroku

环境变量的问题最近由Heroku labs插件解决,它使您的应用程序的heroku config变量在编译期间可访问。要启用此功能,请阅读user_env_compile插件。

另外。使用 asset_sync 与让您的应用程序懒惰地在生产中编译资产或直接在应用服务器上预编译它们相比,性能有了很大提升。不过我会说。我写了。

  • 使用asset_sync和S3,您可以预编译资产,这意味着所有资产都可以立即在资产主机/ CDN上提供服务
  • 您只能在预编译中的application.rb中需要:assets 包,从而节省生产中的内存
  • 您的应用服务器永远不会受到资产请求的影响。你知道,你可以花费昂贵的计算时间。计算
  • 最佳实践HTTP缓存标头默认设置为
  • 您可以使用一个额外的配置启用自动gzip压缩

答案 2 :(得分:2)

这就是我想出的。在需要应用程序配置的资产中,我将此行放在最开头:

<% 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,但比在资产文件中嵌入配置好多倍。

答案 3 :(得分:1)

对于Heroku,我正在运行Asset Sync gem将我的文件存储在CDN上,以避免使用Heroku来获取静态图像。它工作得很好。我还初始化了precompile false,但Asset Sync运行它自己的初始化程序,因此您可以将代码放入其中。 https://github.com/rumblelabs/asset_sync

答案 4 :(得分:0)

虽然在资产预编译时你的初始化程序没有运行,你仍然应该发现它们像Rails一样正常运行,但是,这将是第一次打到应用程序而不是部署步骤。

我不完全确定您遇到的问题是什么,但如果您遵循Rails约定,部署将按预期工作。