How to disable default asset timestamps for some assets in rails? - ruby-on-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!

Related

Rails application returns 404 for images even after rake assets:precompile

I have Rails 4 application deployed on Digital Ocean. Everything went smoothly but the app returns 404 for images:
I, [2014-07-20T22:28:00.693171 #7751] INFO -- : Started GET "/assets/left.png" for 128.73.51.11 at 2014-07-20 22:28:00 +0000
F, [2014-07-20T22:28:00.695271 #7751] FATAL -- :
ActionController::RoutingError (No route matches [GET] "/assets/left.png"):
vendor/bundle/ruby/2.0.0/gems/actionpack-4.1.0/lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
After some googling I found this this and it is said that I can use either config.serve_static_assets = true or rake assets:precompile. I tried both but still have 404 for fonts and images (CSS and JS) are OK.
Can anyone help with this?
This might not solve your issue directly - it's more a clarification on what may be going wrong :)
Fingerprinting
Without knowing your app setup properly, this is just something to consider, but the main cause of this particular issue is the idea of asset fingerprinting
Fingerprinting is basically where Rails will take your asset files, compile them into single files (typically application.css / application.js), and allow you to reference those files as you wish.
The problem here is that if you're serving static assets, which have been fingerprinted, you won't be able to reference them as "static" assets from your CSS / JS any more. You'll have to use dynamic references:
Paths
Dynamic references are basically where you use something like asset_path - which allows you to reference the paths as you require regardless of their filename
Typically, you'll have CSS set up like this:
#app/stylesheets/application.css
body {
background: url("your/image.png");
}
The problem here is that this will reference the image directly, and won't be able to use the dynamic fingerprinted path which is required. To fix this, you'll need to use one of the Rails CSS pre-processors (SASS & SCSS):
#app/assets/stylesheets/application.css.scss
body {
background: asset_url("your/image.png"); /* Notice the path helper? */
}
The issue of dynamically referenced filenames / paths will be one of the issues you'll likely be facing with your application. Without seeing how you're referencing the images, I can only speculate - but I'd recommend taking a look at which path / asset helpers you're using

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 why is .css.scss and .html.haml necessary?

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.

Rails 4 image-path, image-url and asset-url no longer work in SCSS files

Are we supposed to use something else aside from image-url and others in Rails 4? They return different values that don't seem to make sense. If I have logo.png in /app/assets/images/logo.png and I do the following, this is what I get:
image-url("logo.png") -> url("/images/logo.png") #obviously doesn't work
image-path("logo.png") -> "/images/logo.png"
asset-url("logo.png") -> url("/logo.png")
Of course none of these work because they need at least /assets in front.
UPDATE: Actually, I just noticed, how do I access images in Rails 4? I have an image at /app/assets/images/logo.png. But if I go to any of the following URLs, I still don't see my image:
http://localhost:3000/assets/logo.png
http://localhost:3000/assets/images/logo.png
http://localhost:3000/logo.png
http://localhost:3000/images/logo.png
UPDATE 2: The only way I can bring up my logo.png is by moving it into the /app/assets/stylesheets directory and then pulling up:
http://localhost:3000/assets/logo.png
I just had this issue myself.
3 points that will hopefully help:
If you place images in your app/assets/images directory, then you should be able to call the image directly with no prefix in the path. ie. image_url('logo.png')
Depending on where you use the asset will depend on the method. If you are using it as a background-image: property, then your line of code should be background-image: image-url('logo.png'). This works for both less and sass stylesheets. If you are using it inline in the view, then you will need to use the built in image_tag helper in rails to output your image. Once again, no prefixing <%= image_tag 'logo.png' %>
Lastly, if you are precompiling your assets, run rake assets:precompile to generate your assets, or rake assets:precompile RAILS_ENV=production for production, otherwise, your production environment will not have the fingerprinted assets when loading the page.
Also for those commands in point 3 you will need to prefix them with bundle exec if you are running bundler.
Your first formulation, image_url('logo.png'), is correct. If the image is found, it will generate the path /assets/logo.png (plus a hash in production). However, if Rails cannot find the image that you named, it will fall back to /images/logo.png.
The next question is: why isn't Rails finding your image? If you put it in app/assets/images/logo.png, then you should be able to access it by going to http://localhost:3000/assets/logo.png.
If that works, but your CSS isn't updating, you may need to clear the cache. Delete tmp/cache/assets from your project directory and restart the server (webrick, etc.).
If that fails, you can also try just using background-image: url(logo.png); That will cause your CSS to look for files with the same relative path (which in this case is /assets).
I just found out, that by using asset_url helper you solve that problem.
asset_url("backgrounds/pattern.png", image)
I had a similar problem, trying to add a background image with inline css. No need to specify the images folder due to the way asset sync works.
This worked for me:
background-image: url('/assets/image.jpg');
Rails 4.0.0 will look image defined with image-url in same directory structure with your css file.
For example, if your css in assets/stylesheets/main.css.scss, image-url('logo.png') becomes url(/assets/logo.png).
If you move your css file to assets/stylesheets/cpanel/main.css.scss, image-url('logo.png') becomes /assets/cpanel/logo.png.
If you want to use image directly under assets/images directory, you can use asset-url('logo.png')
for stylesheets:
url(asset_path('image.jpg'))
In case anyone arrives looking for how to generate a relative path from the rails console
ActionView::Helpers::AssetTagHelper
image_path('my_image.png')
=> "/images/my_image.png"
Or the controller
include ActionView::Helpers::AssetTagHelper
image_path('my_image.png')
=> "/images/my_image.png"

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

Resources