Ok, so I converted this layered application to use the asset pipeline introduced in Rails 3.1. For the most part, it was surprisingly easy, and I'm in love with the preprocessing ability, which allows you to use embedded Ruby in your CSS / JS files. However, I ran into a serious problem that, despite the power of Sprockets, seems difficult to solve. My application can be launched with any number of skins (or "identity") that are selected at runtime. This "identity" parameter sets things like the cache directory, database connection, browse paths - and even resource paths. Although all โidentifiersโ can have their own stylesheet, there is also a common one that is used in all instances. Thus, the asset folder structure looks something like this:
In / app / assets / stylesheets / aplication.css.erb:
<% require_asset("shared.css") %> <% require_asset("overrides.css") %>
This loads two stylesheets, and to a decisive extent, it uses the configured resource paths to eliminate them (so I use require_assets
instead of the standard require
and include
directives, since they do not get into the converter). It returns the found first matches and allows me to very easily override part or all of the default style. So
/app/assets/stylesheets/shared.css
can be overridden by placing the file with the same name in the instance resource folder
/app/assets/[identity]/stylesheets/shared.css
and if such a file does not exist, it quietly reverts to the default shared.css.
Everything works brilliantly - I use the same technique for Javascripts, images and fonts, and everything is neatly processed and packaged during pre-compilation. BUT. There is a type of (lateral) inheritance that I cannot achieve; sometimes the skin for identity is so similar to another that several separate lines are distinguished (for example, an identical layout, but with a different color scheme), and I really want to be able to do something like this:
assets / style sheets /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") %> ...
This is MALFUNCTION, because in the current context, "some_other_identity" is not in the path to the resources - Rails does not find the file in dev mode, and, of course, it does not turn on during pre-compilation. And if I include it in the asset path, it will load the wrong overrides.css (there can be only one). So I experimented with putting something like this at the top of overrides.css:
<%= File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css")) %> ...
And indeed, it works as expected. BUT. Since I now use the asset pipeline to serve all assets, I can no longer reference CSS images with a fixed path - I must use <%= asset_path("some_image.png") %>
so that the path resolver can work with its magic. This means that my overrides.css
really overrides.css.erb
, and of course, preprocessing ERB does not happen when you do File.read()
. So I'm stuck! Help! Anyone?
Edit: If I use
<%= ERB.new(File.read(Rails.root.join("app/assets/some_other_identity/stylesheets/overrides.css.erb"))).result %>
he is trying to parse ERB but I get
undefined method `asset_path' for main:Object
which, of course, is associated with the use of asset_path("some_image.png")
, etc. in the file I'm trying to include.