【发布时间】: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 而不是标准的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") %>
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 中的图像 - 我必须使用 <%= asset_path("some_image.png") %> 以便路径解析器可以发挥其魔力。这意味着我的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