У меня есть приложение с несколькими родителями Rails 3.2, где каждый «дом» имеет свой собственный скин. Активы для них прекомпилированы с помощью пользовательской Rake задачи:Предварительные компиляции для многоуровневого Rails-приложения
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 принимает необязательный параметр «домашнего», и будут собирать только активы для этого «домов», если поставок - если бы не она перебирает все «дома» и собирает активы для каждого один:
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
Я пытался найти решение этой проблемы в течение нескольких дней в настоящее время но не смогли придумать что-нибудь, что сработало - не помогло, ужасно простудилось и вообще чувствовало себя немного изношенным :(Мне кажется, что это должен быть довольно распространенный сценарий, поэтому я надеюсь, что кто-то здесь будет знать, что делать ...
и что, если вы установите среду RAILS_GROUPS = assets var? 'rake assets precompile: homes RAILS_ENV = production RAILS_GROUPS = активы IDK, если это будет работать, но RAILS_GROUPS var влияет на поведение прекомпиляции. –
, вы можете создать новую среду (например, config/environment/deploy-assets.rb), скопированную с производства и предварительно скомпилированную с ней ('rake assets precompile: homes RAILS_ENV = 'deploy-assets''). –
@ Daniel: настройка 'RAILS_GROUPS = assets' - большое предложение, которое имеет большой смысл - увы, ошибка остается прежней. У меня есть группа «активы» в Gemfile, которая включает в себя «sass-rails» и «uglifier» (сам Sprockets в комплекте с Rails). –