Rails resource pipeline - how to include an asset not in the asset path?

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") %> /* followed by the dosen or so lines that differ for this skin */ ... 

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")) %> /* rest of 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.

+6
source share
1 answer

Well, after several hours of searching, I came across a list of available helper methods in Sprockets - this would save me a lot of time; this is due to the Sprockets man page on GitHub (there is a link, but it points to #FIXME). From the Sprockets API documentation:

  • (Object) evaluate(path, options = {})
  • Reads path and starts processors in the file.
  • This allows you to capture the result of an asset and incorporate it directly into another.
  • <%= evaluate "bar.js" %>

Bingo! I changed my include directive:

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

and CSS is being processed, and the results are being added, just the way I wanted it to work.

+5
source

Source: https://habr.com/ru/post/918876/


All Articles