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

Joh*_*lze 6 ruby-on-rails erb asset-pipeline

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

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

<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>
Run Code Online (Sandbox Code Playgroud)

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

/app/assets/stylesheets/shared.css
Run Code Online (Sandbox Code Playgroud)

可以通过在实例资源文件夹中放置具有相同名称的文件来覆盖

/app/assets/[identity]/stylesheets/shared.css
Run Code Online (Sandbox Code Playgroud)

如果没有这样的文件,它会默默地回退到默认的shared.css.

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

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

<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>
Run Code Online (Sandbox Code Playgroud)

资产/ current_identity /样式表/ overrides.css:

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

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

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

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

编辑:如果我使用

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

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

undefined method `asset_path' for main:Object
Run Code Online (Sandbox Code Playgroud)

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

Joh*_*lze 5

好吧,经过几个小时的搜索后,我找到了Sprockets中可用的辅助方法列表 - 如果从GitHub上的Sprockets手册页链接到它,它会节省我很多时间(有一个链接,但它指向#整我).从Sprockets API文档:

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

答对了!我将include指令更改为:

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

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