2015-02-15 3 views
0

У меня есть приложение с несколькими родителями 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 

Я пытался найти решение этой проблемы в течение нескольких дней в настоящее время но не смогли придумать что-нибудь, что сработало - не помогло, ужасно простудилось и вообще чувствовало себя немного изношенным :(Мне кажется, что это должен быть довольно распространенный сценарий, поэтому я надеюсь, что кто-то здесь будет знать, что делать ...

+0

и что, если вы установите среду RAILS_GROUPS = assets var? 'rake assets precompile: homes RAILS_ENV = production RAILS_GROUPS = активы IDK, если это будет работать, но RAILS_GROUPS var влияет на поведение прекомпиляции. –

+0

, вы можете создать новую среду (например, config/environment/deploy-assets.rb), скопированную с производства и предварительно скомпилированную с ней ('rake assets precompile: homes RAILS_ENV = 'deploy-assets''). –

+0

@ Daniel: настройка 'RAILS_GROUPS = assets' - большое предложение, которое имеет большой смысл - увы, ошибка остается прежней. У меня есть группа «активы» в Gemfile, которая включает в себя «sass-rails» и «uglifier» (сам Sprockets в комплекте с Rails). –

ответ

0

Я ценю, что Rails 3.2 немного мимо его продажи по дате, что с Rails 5 having been announced и все, но до тех пор, пока кто-то не пожертвует месяцем свободного времени (свяжитесь со мной для деталей) Я должен буду продолжать эту работу нин. К счастью, как только мой холодный рассеялся, это было не слишком сложно, чтобы решить эту проблему, у меня был - вот то, что неподвижная задача 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 

Так что это все работает довольно много, как именно Я хотел, до тех пор, пока он запускается в среде разработки, и это нормально - проблема решена.

Edit: Итак, я заметил, что ссылки на активы внутри SCSS файлы не были даны имя файла дайджеста, а некоторые дальнейшие испытания показали, что config.assets.digest = trueделает нужно установить после того, как все. Вышеупомянутый код был обновлен, чтобы отразить это. В противном случае digest_assets ошибочен, когда actionpack/lib/sprockets/helpers/rails_helper.rb проверяет if digest_assets && options[:digest] != false