【问题标题】:Rails asset pipeline - how to include asset not in asset path?Rails 资产管道 - 如何在资产路径中包含资产?
【发布时间】:2012-06-24 15:04:40
【问题描述】:

我已将我的这个多皮肤应用程序转换为使用 Rails 3.1 中引入的资产管道。在大多数情况下,它非常简单,而且我喜欢预处理功能,它允许您在 CSS/JS 文件中使用内联 Ruby。

我遇到了一个大问题,尽管 Sprockets 的强大功能似乎很难解决。我的应用程序可以使用在运行时选择的任意数量的皮肤(或“身份”)运行。这个“身份”参数设置了缓存目录、数据库连接、视图路径——实际上还有资产路径。虽然所有“身份”都可以有自己的样式表,但也有一个共享的样式表,用于所有实例。所以资产文件夹结构看起来像这样:

在 /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。

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

资产/样式表/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 dozen or so lines that differ for this skin */
...

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

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

确实,这和预期的一样有效。但。因为我现在使用资产管道来提供所有资产,所以我不能再使用固定路径引用 CSS 中的图像 - 我必须使用 &lt;%= asset_path("some_image.png") %&gt; 以便路径解析器可以发挥其魔力。这意味着我的overrides.css 真的是overrides.css.erb,当然,当您执行File.read() 时,ERB 预处理不会发生。所以,我被困住了!帮助!有人吗?

编辑:如果我使用

<%= 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") 等。

【问题讨论】:

  • 我想也许将 .erb 扩展名添加到 File.read() CSS 文件名可以解决它(因为它被包含在一个也是 .erb 文件的文件中)但它从来没有那么简单,是吗?
  • 而且也不能使用render() - see this question

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


【解决方案1】:

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

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

宾果!我将包含指令更改为:

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

CSS 得到处理并插入结果,这正是我希望它工作的方式。

【讨论】:

  • 感谢您的参考,帮助了我。
猜你喜欢
  • 2019-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
相关资源
最近更新 更多