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

jsh*_*kol 17 heroku ruby-on-rails-3 ruby-on-rails-3.1 asset-pipeline ruby-on-rails-3.2

背景

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

App配置

我将特定于应用程序的配置保存在名为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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


我的问题

initialize_on_precompile = false设置,没有在初始化的config/initializers/*被运行.我遇到的问题是我需要APP_CONFIG变量在资产预编译期间可用.

如何load_app_config.rb在不初始化整个应用程序的情况下在资产编译期间加载?我可以使用group传递给Rails :: Application.initialize 的参数做些什么!?

Gab*_*ley 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
Run Code Online (Sandbox Code Playgroud)

您无需检查AppConfig是否已定义,因为它只会在资产组中运行.

你可以(而且应该)继续使用initialize_on_precompile = false.load_config.rb初始化程序将在初始化应用程序时运行(因为它已经存在config/initializers)预编译而不进行初始化(因为上面的代码).

  • 到目前为止,这是解决这个问题最干净,最直接的方法.为什么没有其他人投票呢?有用... (5认同)

小智 7

绝对检查github上的asset_sync.或者我们的Heroku开发中心关于在Heroku上使用CDN资产Host with Rails 3.1的文章.

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

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

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