我有一个多宿主的Rails 3.2应用程序,其中每个" home"有自己的皮肤。这些资产是使用自定义Rake任务预编译的:
require "fileutils"
namespace :assets do
namespace :precompile do
task :homes, [:short_name] => ["assets:environment"] do |t, args|
include Sprockets::Helpers::RailsHelper
homes = args.short_name ? home.where(:short_name => args.short_name) : home.all
homes.each do |home|
appenv = Rails.application.assets
appenv.clear_paths
paths = [
"app/assets/homes/#{home.short_name}/images",
"app/assets/homes/#{home.short_name}/stylesheets",
"app/assets/homes/#{home.short_name}/javascripts"
]
paths.each{|x| appenv.append_path x}
config = Rails.application.config
config.assets.prefix = home.short_name
config.assets.digest = true
config.assets.debug = false
config.assets.compress = true
target = File.join(Rails.public_path, config.assets.prefix)
puts "Compiling assets for #{home.name} into #{target}"
Sprockets::StaticCompiler.new(appenv, target, ["*"], digest: true, manifest: true).compile
Sprockets::StaticCompiler.new(appenv, target, ["*"], digest: false, manifest: true).compile
end
end
end
end
这个Rake任务需要一个可选的" home"参数,并且只会编译那个" home"如果提供 - 如果没有它循环通过所有"家庭"并为每一个编译资产:
rake assets precompile:homes[my_home]
或
rake assets precompile:homes
在我的ApplicationController中,我动态设置资产路径:
MyApp::Application.config.assets.prefix = @home.short_name
MyApp::Application.config.assets.digests = YAML.load_file(File.join(Rails.public_path, @home.short_name, "manifest.yml"))
这非常有效 - 只要我在开发环境中运行Rake任务 - 但是在生产中运行时,我在appenv.clear_paths
上尝试修改环境时出错:
$ rake assets precompile:homes RAILS_ENV=production
TypeError: can't modify immutable index
/var/rails/MyApp/vendor/ruby/1.9.1/gems/sprockets-2.2.3/lib/sprockets/index.rb:80:in `expire_index!'
/var/rails/MyApp/vendor/ruby/1.9.1/gems/sprockets-2.2.3/lib/sprockets/trail.rb:49:in `clear_paths'
/var/rails/MyApp/lib/tasks/assets.rake:10:in `block (4 levels) in <top (required)>
我理解这是因为Sprockets使用不同的对象来表示生产中的appenv,在开发中这是完整的环境(Sprockets :: Environment),而在生产中它是一个简化和受限的子集(Sprockets :: Index) )这是只读的。但是这导致了一个问题22:为了能够在我需要在开发中运行它的任务中动态设置资产路径,但是为了压缩和缩小资产,并使摘要工作,我有在生产中运行它。正如你所看到的,我试图在开发过程中强制它压缩并生成摘要,但这似乎没有效果:
config.assets.digest = true
config.assets.debug = false
config.assets.compress = true
我一直试图找到一个解决方案,但是现在已经找不到任何有效的方法了 - 没有一个严重的感冒和一般感觉有点疲惫的帮助:(在我看来,这应该是一个相当普遍的情况,所以我希望这里有人知道该怎么做......
答案 0 :(得分:0)
我很欣赏Rails 3.2有点过时了,Rails 5 having been announced以及所有这些,但直到有人捐出一个月的空闲时间(联系我了解详情)我和#39;我必须保持这个东西运行。幸运的是,一旦我的感冒消失了,解决我遇到的问题并不是太难 - 这就是固定的Rake任务的样子:
require "fileutils"
namespace :assets do
namespace :precompile do
task :homes, [:short_name] => ["assets:environment"] do |t, args|
include Sprockets::Helpers::RailsHelper
homes = args.short_name ? home.where(:short_name => args.short_name) : home.all
homes.each do |home|
appenv = Rails.application.assets
appenv.clear_paths
paths = [
"app/assets/homes/#{home.short_name}/images",
"app/assets/homes/#{home.short_name}/stylesheets",
"app/assets/homes/#{home.short_name}/javascripts"
]
paths.each{|x| appenv.append_path x}
config = Rails.application.config
config.assets.prefix = home.short_name
config.assets.digest = true
target = File.join(Rails.public_path, config.assets.prefix)
puts "Compiling assets for #{home.name} into #{target}"
Sprockets::StaticCompiler.new(appenv, target, ["*"], digest: false, manifest: false).compile
Sprockets::StaticCompiler.new(appenv, target, ["*"], digest: true, manifest: true).compile
end
end
end
end
这与我之前的几种方式不同:
debug
上设置compress
和Rails.application.assets
选项,因为这些选项显然没有效果。 第二个更改解决了丢失的摘要问题,并且environments/development.rb
资产中的以下内容被缩小,CSS文件不再包含SASS行号注释:
config.assets.debug = false
config.assets.compress = true
所以它完全按照我想要的方式工作,只要它在开发环境中运行,这很好 - 问题已解决。
编辑:所以,我注意到SCSS文件中的资产引用没有给出摘要文件名,一些进一步的测试显示config.assets.digest = true
需要毕竟是设定的。上面的代码已更新以反映这一点。当actionpack / lib / sprockets / helpers / rails_helper.rb检查digest_assets
if digest_assets && options[:digest] != false
为false