我已经转换了我的这个多皮肤应用程序,以利用 Rails 3.1 中引入的资产管道。在大多数情况下,它非常简单,我爱上了预处理能力,它允许您在 CSS/JS 文件中使用内联 Ruby。
不过,我遇到了一个大问题,尽管 Sprockets 的强大功能似乎很难解决。我的应用程序可以使用在运行时选择的任意数量的皮肤(或“身份”)运行。这个“身份”参数设置了缓存目录、数据库连接、视图路径——实际上还有资产路径。虽然所有“身份”都可以拥有自己的样式表,但也有一个共享的样式表,用于所有实例。所以资产文件夹结构看起来像这样:
在 /app/assets/stylesheets/aplication.css.erb 中:
<% require_asset("shared.css") %>
<% require_asset("overrides.css") %>
这会加载两个样式表,关键是它使用配置的资产路径来解析它们(这就是我使用require_assets
而不是标准require
和include
指令的原因,因为它们不会命中解析器)。它返回找到的第一个匹配项,并允许我非常轻松地覆盖部分或全部默认样式。所以
/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") %>
资产/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 中的图像 - 我必须使用<%= asset_path("some_image.png") %>
这样的路径解析器才能发挥其魔力。这意味着 myoverrides.css
是真的overrides.css.erb
,当然,当你这样做时,ERB 预处理不会发生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")
在我试图包含的文件中使用了 etc 。