Ruby on rails Rails 3.1资产管道未预编译来自不同目录的文件

Ruby on rails Rails 3.1资产管道未预编译来自不同目录的文件,ruby-on-rails,ruby-on-rails-3.1,asset-pipeline,Ruby On Rails,Ruby On Rails 3.1,Asset Pipeline,我目前有一个Rails 3.1应用程序,为几个不同的客户托管多个站点。 每个站点都由一个模型表示,该模型知道存储资产的域名和路径,以及一些其他信息 我一直在使用app/sites/domain name作为存储特定于给定站点的资产、视图和区域设置的位置,并正在运行自定义中间件和控制器操作,以修改链轮的加载路径、设置视图路径等 中间件(使用config.middleware.use在application.rb中的“Configurator”加载): 来自应用程序.rb的资产位: class Co

我目前有一个Rails 3.1应用程序,为几个不同的客户托管多个站点。 每个站点都由一个模型表示,该模型知道存储资产的域名和路径,以及一些其他信息

我一直在使用
app/sites/domain name
作为存储特定于给定站点的资产、视图和区域设置的位置,并正在运行自定义中间件和控制器操作,以修改链轮的加载路径、设置视图路径等

中间件(使用
config.middleware.use在
application.rb
中的“Configurator”加载):

来自
应用程序.rb的资产位:

class Configurator
  def initialize(app)
    @app = app
  end

  def call(env)
    @env = env
    clear_existing_paths
    prepend_local_assets
    @app.call(env)
  end

  def current_site
    # find site using @env
  end

  def current_site_path
    Rails.root.join('app', 'sites', current_site.path)
  end

  def clear_existing_paths
    paths = Rails.application.assets.paths
    Rails.application.assets.clear_paths
    paths.each do |path|
      next if path.include?("app/sites/")
      Rails.application.assets.append_path path
    end
  end

  def prepend_local_assets
    path = current_site_path.join('assets')
    return unless Dir.exists?(path)

    ['images', 'javascripts', 'misc', 'stylesheets'].each do |subdir|
      asset_dir = path.join(subdir).to_s
      next unless Dir.exists?(asset_dir)
      next if     Rails.application.assets.paths.include? asset_dir

      Rails.application.assets.prepend_path asset_dir
    end
  end
end
module MyApp
  class Application < Rails::Application
    ...
    config.middleware.use "Configurator"

    config.assets.enabled = true 
    config.assets.version = '1.0'
  end
end
MyApp::Application.configure do
  config.serve_static_assets = false
  config.assets.compress = true
  config.assets.compile = true
  config.assets.digest = true
  # Defaults to Rails.root.join("public/assets")
  # config.assets.manifest = YOUR_PATH
end
{ "sitename" => "shortname", ... }.each_pair do |domain, short|
  %w{stylesheets javascripts}.each do |dir|
    config.assets.paths << Rails.root.join("app/sites/#{domain}/assets/#{dir}").to_s
  end # Had to specify each dir to make it work
  config.assets.precompile += ["#{short}/site.css", "#{short}/site.js"]
end
问题是,虽然这个设置有效,但它阻止我预编译未与整个应用共享的资产,使它们从外观上一次又一次地生成

我是否可以告诉预编译器找到位于此处的资产,并创建这些资产的版本?每个站点都有一个
site.css.scss
和一个
site.js.coffee
文件,可能需要站点目录中的其他资源。如果我能将它预编译到
公共/资产/域名/站点(js | css)
,那就太好了,这样当我需要进一步优化时,我就可以轻松地为资产设置一个单独的子域

最终解决方案(2012-02-22) 在实现了Brian的建议后,我最终得到了

存储在
app/sites//assets//site.css | js
中的主样式表/javascript,其中
sitename
是此站点的域,
shortname
是域的主要部分,没有子域或com | org | net | ccTLD

修改了所有视图和样式表,将
shortname
前置到我的资产路径

config/application.rb
中:

class Configurator
  def initialize(app)
    @app = app
  end

  def call(env)
    @env = env
    clear_existing_paths
    prepend_local_assets
    @app.call(env)
  end

  def current_site
    # find site using @env
  end

  def current_site_path
    Rails.root.join('app', 'sites', current_site.path)
  end

  def clear_existing_paths
    paths = Rails.application.assets.paths
    Rails.application.assets.clear_paths
    paths.each do |path|
      next if path.include?("app/sites/")
      Rails.application.assets.append_path path
    end
  end

  def prepend_local_assets
    path = current_site_path.join('assets')
    return unless Dir.exists?(path)

    ['images', 'javascripts', 'misc', 'stylesheets'].each do |subdir|
      asset_dir = path.join(subdir).to_s
      next unless Dir.exists?(asset_dir)
      next if     Rails.application.assets.paths.include? asset_dir

      Rails.application.assets.prepend_path asset_dir
    end
  end
end
module MyApp
  class Application < Rails::Application
    ...
    config.middleware.use "Configurator"

    config.assets.enabled = true 
    config.assets.version = '1.0'
  end
end
MyApp::Application.configure do
  config.serve_static_assets = false
  config.assets.compress = true
  config.assets.compile = true
  config.assets.digest = true
  # Defaults to Rails.root.join("public/assets")
  # config.assets.manifest = YOUR_PATH
end
{ "sitename" => "shortname", ... }.each_pair do |domain, short|
  %w{stylesheets javascripts}.each do |dir|
    config.assets.paths << Rails.root.join("app/sites/#{domain}/assets/#{dir}").to_s
  end # Had to specify each dir to make it work
  config.assets.precompile += ["#{short}/site.css", "#{short}/site.js"]
end
{“sitename”=>“shortname”,…}。每个_对都是|域,short|
%w{stylesheets javascripts}。每个do|dir|

config.assets.paths看起来Rails至少在我将config/environments/production.rb更改为包含时能够找到资产

config.assets.precompile += %w( site.js site.css )
config.assets.paths << Rails.root.join("app/sites/sitename/assets/stylesheets").to_s
config/application.rb
以包括

config.assets.precompile += %w( site.js site.css )
config.assets.paths << Rails.root.join("app/sites/sitename/assets/stylesheets").to_s

config.assets.paths我认为问题在于,通过将每个站点添加为路径,链轮只能找到第一个site.scss

我已经用指南针试过了,但是普通链轮应该是一样的。 我还没有尝试过您的配置器方法,但它看起来很容易使我的安排适应它

你能把你的应用程序/网站/*改成更标准的文件格式吗

./app/assets/javascripts/application.js
./app/assets/stylesheets/screen.css.scss
./app/assets/stylesheets/othersite/screen.css.scss
更改config/application.rb,并添加每个站点。 这将在每个主机上预生成所有样式:

config.assets.precompile += ['screen.css', 'othersite/screen.css']
在视图/布局/应用程序中,需要配置sitename的路径:

= stylesheet_link_tag '[your sitename here]/screen'
在我rake assets:clean和precompile之后,我在公共场合看到了这一点:

./assets/othersite/screen.css
./assets/othersite/screen.css.gz
./assets/screen.css
./assets/screen.css.gz

看来你基本上已经明白了。我想你会被困在最后一点上,因为config.assets.paths-在末尾放上“样式表”。我更愿意保留这些资产,因为
app/sites/
还包含我们覆盖的视图(主要是邮件模板等)和特定站点的区域设置,虽然剩下的似乎是我必须要做的。最后我试了试,它就像一个符咒!这是当之无愧的赏金,因为这件事让我烦了好几年了。更新了我的问题,以防其他人有类似的解决方案