如何告诉Rails资产生成新的公共资产文件

时间:2014-03-19 18:38:39

标签: ruby-on-rails ruby-on-rails-4 sprockets

我有一个Rails应用程序,它根据您访问网站的域名动态创建和编译资产(比如说不同颜色,颜色值存储在数据库中)

让我们说www.hello.example它会生成public/assets/hello-application-52777d36dec6f6e311560156da9da1c2.css所以浏览器源文件会指向

layout:
= stylesheet_link_tag 'hello-application'

generated html:
<link href="/assets/hello-application-52777d36dec6f6e311560156da9da1c2.css" media="all" rel="stylesheet" />

如果添加www.goodbye.example,则会编译public/assets/goodbye-application-52777d36dec6f6e311560156da9da1c2.css,因此浏览器源文件将指向

layout:
= stylesheet_link_tag 'goodbye-application'

generated html:
<link data-turbolinks-track="true" href="/assets/goodbye-application-52777d36dec6f6e311560156da9da1c2.css" media="all" rel="stylesheet" />

无需重启服务器即可正确编译资产。

如果我重新启动服务器,上面的示例工作正常

我无法弄清楚的是如何告诉Rails生成了新的公共资产文件,以便= stylesheet_link_tag 'goodbye-application'能够选择而无需重新启动生产服务器

我的猜测是告诉Rails重新加载public/manifest.json我无法搞清楚

  • Rails 4.0.2
  • Ruby 2.1
  • Unicorn制作服务器

我的功能有点类似于krautcomputing article,但他正在用#34; Digested&#34;解决这个问题。这不适用于rails 4(+它很快就会被弃用)


更新

一个家伙提供了一个答案(他已删除),表明我不需要这样做,因为Unicorn没有时间重启,所以我可以重新启动独角兽,它将加载新的公共资产......这是真的,在我问这个问题之前,我是这样做的。但是,我正在寻找避免这种情况的解决方案。 (假设用户每天生成1000个样式)

他还建议使用Grunt ......好吧,那个计划B,我真的想知道在Rails-sprockets中是否有办法做到这一点:)

2 个答案:

答案 0 :(得分:1)

为什么不直接推出自己的辅助方法?

def subdomain_application_stylesheet_link_tag(subdomain)
  if Rails.env.production?
    # This assumes you've precompiled the spreadsheet into the public directory via sprockets
    stylesheet_link_tag File.basename(
      Dir.glob("#{Rails.root}/public/assets/#{subdomain}-application-*.css").first
    )
  else
    # Logic to development stylesheet selection
  end
end

答案 1 :(得分:0)

以下是显示重新加载问题的完整解决方案。如原始帖子中所述,除非您完全重新加载服务器(或杀死工作等),否则您动态生成的新manifest.json将不会重新加载。只是重申:

  

如果您动态创建资产'live',还有清单   为防止缓存,Sprockets不会重新加载清单   请求。

我需要这种显式重新加载功能才能进行开发,因为我正在使用Gulp滚动我自己的资产管道以提高性能。基本上,使用这个解决方案可以使资产完全按照它们的生产方式运行,同时在使用新清单进行开发时仍能够重新加载它们......非常光滑,我希望您发现它对您的生产需求很有用。 / p>

创建文件config / initializers / live-manifest.rb:

  require 'sprockets/rails/helper'
  module Sprockets
    module Rails
      module Helper
        def asset_digest_path(path, options = {})
          # create the new manifest, overriding sprockets' old one
          if assets_manifest and manifest = Sprockets::Manifest.new(assets, Dir.glob(File.join(assets_manifest.dir, 'manifest-*.json')).first)
            if digest_path = manifest.assets[path]
              return digest_path
            end
          end

          if environment = assets_environment
            if asset = environment[path]
              return asset.digest_path
            end
          end
        end
      end
    end
  end

此外,如果您愿意,非常欢迎您自定义新的清单目录。正如您在Dir.glob方法调用中所看到的,Mine与前一个位置在同一个位置,具有不同的名称。