Rails资产管道 - 如何将资产包括在资产路径中?

时间:2012-06-24 15:04:40

标签: ruby-on-rails asset-pipeline erb

好的,所以我已经将我的多皮肤应用程序转换为使用Rails 3.1中引入的资产管道。在大多数情况下,它非常简单,我喜欢预处理能力,它允许您在CSS / JS文件中使用内联Ruby。我遇到了一个主要问题,尽管Sprockets的强大功能似乎很难解决。我的应用程序可以使用在运行时选择的任意数量的皮肤(或“身份”)来运行。这个“身份”参数设置了缓存目录,数据库连接,视图路径以及资产路径等内容。虽然所有“身份”都可以拥有自己的样式表,但还有一个共享的样式表可用于所有实例。所以assets文件夹结构如下所示:

在/app/assets/stylesheets/aplication.css.erb中:

<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>

这会加载两个样式表,最重要的是它使用配置的资产路径来解决它们(这就是我使用require_assets而不是标准requireinclude指令的原因,因为它们不会击中解析器)。它返回找到的第一个匹配项,并允许我非常轻松地覆盖部分或全部默认样式。所以

/app/assets/stylesheets/shared.css
可以通过在实例资产文件夹中放置一个具有相同名称的文件来覆盖

/app/assets/[identity]/stylesheets/shared.css

如果不存在此类文件,则会以静默方式回退到默认的shared.css。

这一切都运行得非常出色 - 我对Javascripts,图像和字体使用相同的技术,在预编译期间,所有内容都得到了整齐的处理和打包。但。有一种(横向)继承我无法实现; 有时候身份的皮肤非常类似于另一个只有少数几行不同(例如相同的布局但颜色方案不同),我真的希望能够做到这样的事情:

资产/样式表/ application.css.erb:

<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>

assets / current_identity / stylesheets / overrides.css:

<% require_asset("../../some_other_identity/stylesheets/overrides.css") %>
/* followed by the dosen or so lines that differ for this skin */
...

此FAILS因为在当前上下文中“some_other_identity”不在资产路径中--Rails在dev模式下找不到文件,当然也不包括在预编译期间。如果我将它包含在资源路径中,则会加载错误的覆盖.css(只能有一个)。所以我一直在尝试将这样的东西放在overrides.css的顶部:

<%= File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css")) %>
/* rest of CSS */
...

事实上,这与预期一样有效。但。因为我现在正在使用资产管道来提供所有资产,所以我不能再使用固定路径引用CSS中的图像 - 我必须使用<%= asset_path("some_image.png") %>以便路径解析器可以发挥其魔力。这意味着我的overrides.css确实是overrides.css.erb,当然{ER}预处理不会发生File.read()。所以,我被卡住了!救命!任何人?

编辑:如果我使用

<%= ERB.new(File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css.erb"))).result %>

它确实试图解析ERB,但我得到了

undefined method `asset_path' for main:Object

当然是由于我在我试图包含的文件中使用asset_path("some_image.png")等。

1 个答案:

答案 0 :(得分:5)

好的,经过几个小时的搜索后,我遇到了the list of available helper methods in Sprockets - 如果这个链接来自GitHub上的the Sprockets man page,那将会节省我很多时间(有一个链接,但它指向#整我)。来自Sprockets API文档:

  • (Object) evaluate(path, options = {})
  • 读取path并在文件上运行处理器。
  • 这使您可以捕获资产的结果并将其直接包含在另一个资产中。
  • <%= evaluate "bar.js" %>

宾果!我将include指令更改为:

<%= evaluate(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css.erb")) %>

并且CSS被处理并插入结果,就像我希望它的工作方式一样。