我在 s3 上托管我的资产。在生产环境中,rails 正在寻找 /javascripts/cache/all.js 和 /stylesheets/cache/all.css。当我使用 cap 进行部署时,我正在使用插件将公共目录转移到 s3。问题是 Rails 在第一次请求它们之前不会创建这些缓存文件,因此当我传输公共目录时,它们在部署期间并不存在。有没有一种简单的方法可以在部署期间强制创建这些文件?
5 回答
创建缓存文件的实际 rails 模块是ActionView::Helpers::AssetTagHelper
您可以在部署期间重复使用来创建缓存文件的。以下对我来说没问题:
require 'action_view'
class AssetCacheWriter
include ActionView::Helpers::AssetTagHelper
def write
write_asset_file_contents(File.join(JAVASCRIPTS_DIR, "all.js"), compute_javascript_paths([:all], true))
write_asset_file_contents(File.join(STYLESHEETS_DIR, "all.css"), compute_stylesheet_paths([:all], true))
'standard_all')
end
end
write_asset_file_contents
我从 Rails 代码中提取的这两个调用。_DIR
常量在包含的模块中定义,调用中的参数true
指示compute_xxx_paths
所有文件都应递归包含。
我创建了一个简单的 cap 任务,它只是把文件写出来:
namespace :sample
task :assets do
AssetCacheWriter.new.write
end
end
我在 rake 任务文件中使用它。使您免于创建额外的类并保持它 DRY,因为您使用的是stylesheet_link_tag / javascript_include_tag
desc "Clears javascripts/cache and stylesheets/cache" task :clear => :environment do
puts "Clearing javascripts/cache and stylesheets/cache"
FileUtils.rm(Dir['public/javascripts/cache_[^.]*']) # use :cache => 'cache_all.js' in stylesheet_link_tag
FileUtils.rm(Dir['public/stylesheets/cache_[^.]*']) # use :cache => 'cache_all.css' in javascript_include_tag
end
desc "Recreate the javascripts/stylesheets cache."
task :generate => [:environment, :clear] do
puts "Recreate the javascripts/stylesheets cache"
ActionController::Base.perform_caching = true
app = ActionController::Integration::Session.new
app.get '/'
end
如果您使用的是 Engine Yard Cloud,这就是我所做的:
添加了一个文件 /lib/tasks/assetcache.rake
require 'assetwriter'
namespace :assetcache do
desc "Clears javascripts/cache and stylesheets/cache"
task :clear => :environment do
puts "Clearing javascripts/cache and stylesheets/cache"
FileUtils.rm(Dir['public/javascripts/cache_[^.]*'])
# use :cache => 'cache_all.js' in stylesheet_link_tag
FileUtils.rm(Dir['public/stylesheets/cache_[^.]*'])
# use :cache => 'cache_all.css' in javascript_include_tag
end
desc "Recreate the javascripts/stylesheets cache."
task :generate => [:environment, :clear] do
puts "Recreate the javascripts/stylesheets cache"
AssetCacheWriter.new.write
end
end
然后我添加了 /lib/assetwriter.rb
需要“action_view”类 AssetCacheWriter
包括 ActionView::Helpers::AssetTagHelper
def write write_asset_file_contents(File.join(JAVASCRIPTS_DIR, "cache/all.js"), compute_javascript_paths([:all], true)) write_asset_file_contents(File.join(STYLESHEETS_DIR, "cache/all.css"), compute_stylesheet_paths([:全部],真实))结束
结尾
然后我添加到 /deploy/after_restart.rb
运行“cd #{release_path} && bundle exec rake assetcache:generate”
我发现包含顺序很重要(例如,jQuery 在其他脚本之前包含在内),因此使用了以下方法。还允许使用 :defaults。
第一个 lib/asset_pacakger:
require 'action_view'
class AssetCacheWriter
include ActionView::Helpers::AssetTagHelper
include ActionView::Helpers::TagHelper
def write
ActionController::Base.perform_caching = true
stylesheet_link_tag *ApplicationController::STYLESHEET_INCLUDES
javascript_include_tag *ApplicationController::JAVASCRIPT_INCLUDES
end
end
然后是脚本/package_assets:
#!/usr/bin/env ruby
RAILS_ROOT = File.expand_path(File.dirname(__FILE__) + '/../')
Dir.chdir(RAILS_ROOT)
RAILS_ENV = ENV['RAILS_ENV'] || 'development'
puts "Bundling assets for environment #{RAILS_ENV}"
require File.join('config', 'environment')
AssetCacheWriter.new.write
然后是上限任务:
desc "Package assets"
task :package_assets do
%x[#{Dir.getwd}/script/package_assets]
%x[svn commit #{Dir.getwd}/public/javascripts/defaults.js #{Dir.getwd}/public/stylesheets/defaults.css -m "(capistrano) packaging assets to trunk"]
logger.info "packaged assets to trunk"
end
在 Rails 3.0.7 中,上述方法似乎都不起作用。我有很多关于配置未定义的错误。
在查看了 Rails 代码之后,我想出了这个对我有用的解决方案。
lib/tasks/cache_assets.rake
require 'asset_packager'
desc "cache assets"
task :cache_assets do
puts "-----> Caching Assets"
AssetCacheWriter.new.write
puts "-----> Done!"
end
然后是 lib/asset_packager.rb
require 'action_view'
class AssetCacheWriter
include ActionView::Helpers::AssetTagHelper
include ActionView::Helpers::TagHelper
def config
ApplicationController
end
def controller
ApplicationController
end
def write
ActionController::Base.perform_caching = true
# You can replace these with your app's cached assets. They should look the same
# as in your view templates.
stylesheet_link_tag :vendor, :defaults, :cache => 'cached/all'
javascript_include_tag :bd_defaults, :'vendor-head', :cache => 'cached/defaults_vendor'
end
end
然后执行它,只需运行rake cache_assets