我有一个应用程序,我最近更新到Rails 3.2.1(来自Rails 3.0.x)并重构了JS和CSS资产以利用新的资产管道。该应用程序使用Celadon Cedar堆栈托管在Heroku上。
我将特定于应用程序的配置保存在名为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支持内置于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
参数做些什么! ?
答案 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 与让您的应用程序懒惰地在生产中编译资产或直接在应用服务器上预编译它们相比,性能有了很大提升。不过我会说。我写了。
答案 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约定,部署将按预期工作。