Rails why is .css.scss and .html.haml necessary? - ruby-on-rails

Surely Sprockets has enough info if a file is named x.scss and y.haml to assume that by default it should be rendered as css and html (the same applies with CoffeeScript)?

This is used to indicate clearly you want some kind of file.
This may be obvious most of the time so you can skip it.
Actually, this is really needed when you serve different types of views: .pdf, .html for instance. In this case, you have to use .pdf.haml, .html.haml
Same for coffee and scss, I never use .js.coffee, always use .coffee directly.

Related

Rails 4 assets - two different digests getting generated

I clearly must be Doing Something Wrong here. I'm wrestling with the asset pipeline (again). I have a custom font, and it seems to me to get everything to compile properly I need to use asset_path() in multiple places, but it's having an unexpected effect.
I realize there are several ways to do this, but here's what I have currently:
In application.css.scss.erb:
#import "<%= asset_path("my-font.css") %>";
my-font.css's source file is app/assets/stylesheets/my-font.css.erb (it needs to be an .erb because I am also using asset_path() there as well).
In application.rb I am adding my-font.css to the precompile list.
config.assets.precompile << 'my-font.css'
When I clean out public/assets and run rake assets:precompile Everything's getting compiled, with digests, but the digest applied to the actual file is not the same as the digest calculated and put in to application.css.
The resulting file is
public/assets/my-font-2f25682a1ea904a866ef9f44101a5a2e.css but in public/assets/application-bba2edaee36771f4bdb5c89b8ec90aaf.css the reference to it is:
#import url(/assets/my-font-ed843d3b174ca427edf963e473ad9e9b.css);
I realize I'm probably using asset_path() more than I should, and also importing files via url() instead of requiring them, but this has gotten me the closest to having things working.
I suspect one of the digests is being calculated on my-font.css before it goes through ERB, and the other after, but I don't understand why nor how to fix it.
Suggestions?
I would guess that you're cleaning your assets just by emptying public/assets. That's not enough, you'll also need to empty your tmp/cache/assets, or just run rake assets:clobber to do both.
I've resolve this kind of dependency by injecting the raw contents of the asset you want to bundle into a composite asset like application.scss.erb. You need to explicitly declare the dependency (so that changes in my-fonts.css cause a regenerations of application.css) and then inject the contents:
application.scss.erb:
// Should be at Top of File
//= depend_on_asset my-fonts.css
//... wherever in the file you want the contents injected:
<%= environment['my-fonts.css'] %>
How does this work? During asset pipeline compilation, the environment here has a hash of all pre-compiled asset contents. This allows you to inject the compiled contents from my-fonts.css into your composite asset. Because we're manually injecting the value, we need to explicitly create a dependency to track this relationship via depend_on_asset.
One thing to keep in mind is that multiple asset pre-processors (SCSS, ERB, etc) are processed from the "outside in", so the contents of the my-fonts.css asset will be compiled/injected during the ERB processing as CSS output. They will be included within the asset before SCSS processing. This shouldn't pose a problem, because if this is an SCSS asset, any SCSS references will be compiled before injection into the parent asset.

Rails: How to access images in Javascript?

i'm pretty new to Rails and have a little question:
How can i access images in Javascript? SCSS, ERB, ... have methods like "image_path", but i didn't find something similar for Javascript.
I need it to specify the image URLs for the firefly plugin:
$.firefly({images : ['???/1.jpg', '???/2.jpg'],total : 40});
if your image in /app/assets/images/ you can simply use
/assets/1.jpg
Similarly in css, you can use
url(/assets/1.jpg)
You can follow same thing when using in javascript.
$.firefly({images : ['/assets/1.jpg', '/assets/2.jpg'],total : 40});
Note: The above methods will cause problem when your rails app is in sub-directory. In that case use relative path. Asset pre-compilation will compile all assets in public/assets directory. so your structure may be like:
public
-assets
--images
---1.png
--javascripts
--stylesheets
---style.css
so from style.css, you can use relative path like ../images/1.png
When I needed to do this, I inserted the whatever image was required on the page under a div#class and set that class as hidden in my css. Then, in javascript, I could access the image from that div.
May not be ideal solution, but couldn't think of anything else because of asset pipeline.
Also, try accessing image from ./assets/image_name.jpg

Why are Rails assets not isolated between models?

I have these a coffeescript file for a model entree that just instanciates a class in another coffeescript file:
jQuery(document).ready ->
ch = new CepageHandling
ch.handleKeyPress()
The handlePress function captures keyup events on a control.
I have another model vin where I want to enable the same feature. I'm surprised to see I don't need to do anything (it already has the same html), it's already working, even though the coffeescript for the vin model is completely empty. I assume that the created javascript for entree gets called even when I'm not on this page.
I have seen the same behavior with scss files, where style defined for one model gets applied to others if the descriptors match. Can someone explain (or point to some article) if this is normal behavior that assets are not isolated in rails? I really have a hard time grasping how it works.
The default manifest files (application.js, etc) do require_tree . which will load all files on all pages, concat them all together in production, etc. If you want things to be isolated you'll need to put a test in your ready handler to skip this code in some cases, or you'll need more manifests (and not use application.js for example) to silo your code per page. I suggest you read every word of the asset pipeline Rails Guide very carefully... required reading!
It happens because of the manifest file application.js, more precisely in this line of code:
//= require_tree .
What this means is that all .js files contained inside the /assets/javascripts/ folder would be loaded to your views.
As your entree.js is already loaded and using the JQuery document ready function, it searches for the rules of your file inside all of your views.
This means that all of your pages that contains this ch element will get the same behavior.

Using a database value in a LESS file in Rails

I have installed the less-rails gem as I am keen to use the colour manipulation LESS offers. I need to extract a colour from my database as my themes base colour, and build up from there.
I have the static CSS, and have renamed it styles.css.less to ensure that rails understands the less extension, which it appears to.
The next thing I tried was to also wrap the file as an erb, to hopefully allow ruby string literals to process before being sent to LESS, and eventually outputting as valid CSS (still with me?)
The file is now called style.css.less.erb. While the file simple contains valid CSS, the processing of the document works. As soon as I add a ruby string literal, it fails.
color: #{"#112233"};
In the chrome debugger, nothing after this line is getting processed.
What am I doing wrong, and how should I do what I am trying to do?
As Chowlett says in comments, you should use erb syntax: <%= "#112233" %>
Next step is get that value from db. If this color value is application-wide, probably you are looking for settings in db solution. I use rails-settings-cached gem for that. Your result code will looks like
color: <%= Setting.foo_color %>
If you are using assets on production, don't forget to recompile them after each setting change.
And if it's not a setting but probably something specific to each user then you can't use application-wide css files for that, but you can write inline css in views.

How to disable default asset timestamps for some assets in rails?

There are some image assets on my site that will always remain static, and therefore do not need the timestamp that gets appended to the images. Is there a way to not append the timestamps for certain assets?
Why not just use the regular HTML <img> element for those images? It'll be marginally faster than going through the Rails' helper too.
From the Rails docs "You can enable or disable the asset tag timestamps cache. With the cache enabled, the asset tag helper methods will make fewer expense file system calls. However this prevents you from modifying any asset files while the server is running."
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = true
Solution 1 would work, except I still need it to use the asset host, and I don't want to hardcode it. Solution 2 does not work since that would affect all asset paths. I think what I should be doing is to combine using the img tag, but use rails to compute the asset host for me.
So in the end it would look something like this
<img src=\"#{#template.image_path("image.jpg}}\"/>
thanks for the idea!

Resources