I am currently using Rails 4.0.2 with jQuery UI (mostly for the datepicker). My production environment is Heroku.
My main problem is that the images for my theme are not being served in production (while it works fine in development). I am including the theme's css like this in my application.css
:
*= require_self
*= require_tree .
*= require jquery-ui-1.10.4.custom
The theme's css is showing up fine, but none of the images are working. I have read through endless questions on StackOverflow, blogs and discussions on Github - none of which have worked for me. I also read through the Edge Rails guide which doesn't mention a word about image precompilation, even though from the discussions on Github it seems that this has really changed in Rails 4.
Here is my current directory structure:
/vendor
/assets
/stylesheets
jquery-ui-1.10.4.custom.css
/images
animated-overlay.gif
ui-bg_flat_0_aaaaaa_40x100.png
(more images like these)
As far as I know the correct way of integrating external css and javascript libraries is to put those assets inside /vendor/assets so that is what I'm doing.
So again, my problem is that rails flatly refuses to serve any assets in production. I can fiddle with the image URL, but it's simply not getting served.
Here are things I have tried:
If I run rake assets:precompile
I only see 2 files inside public/assets - a css file and a javascript file. I'm assuming this is wrong and that Rails should actually put my images there as well.
According to this question - rails 4 asset pipeline vendor assets images are not being precompiled - you need to explicitly tell Rails that you want images to be precompiled. (This seems rather insane to me, since I am pretty sure I am not the only Rails 4 site on the internet serving images. Is everyone else just using text and ASCII art?)
So I added this to my application.rb
:
config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif)
Now when I run rake assets:precompile
all my vendor assets are being compiled, fingerprinted and put in public/assets/images
. This has no effect in production though, I suspect that Rails is simply refusing to serve the default assets and will only serve the fingerprinted assets.
Some of the other things I read suggested that you need to manually specify the images path if it is outside of app/assets (since mine is in vendor/assets this seems to qualify).
config.assets.paths << Rails.root.join('vendor', 'assets', 'stylesheets', 'images')
When I now run rake assets:precompile
my images are no longer being precompiled or fingerprinted, but they are also not being served in production.
According to this blog post - JQuery-UI css and images, and Rails Asset Pipeline - this is because Sprockets will see that a path is already included and will exclude it and you can fix it by prepending the path in application.rb
.
initializer :after_append_asset_paths,
:group => :all,
:after => :append_assets_path do
config.assets.paths.unshift Rails.root.join("vendor", "assets", "stylesheets", "images").to_s
end
This also had no effect. When I run rake assets:precompile it doesn't compile or fingerprint my images and it doesn't show up in production. That post is targeted at Rails 3 so I didn't really have high hopes.
Even though this seems wrong to me (in the Rails sense) I moved all the images to app/assets/images. This still had the same result - images are not showing up in production. I also tried combining this with the trick of forcing images to be included in compilation:
config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif)
But it didn't have any effect. I suspect Rails is simply being stubborn and not serving the non-fingerprinted assets.
The images being requested are done via css, so if I look in the actual theme's css file there are lines like this:
background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;
Some things I read (mostly in the comments/complaints on Github and blog posts) suggested that the /images
at the beginning of the url is screwing with me. So I manually went into the file and removed it everywhere, which had no effect - meaning images still didn't show up in production.
According to this post - Rails 4: How To Fix The Heroku Assets Not Found CSS Image Issue - I should add this to my production.rb
config.assets.compile = true
I really don't want to do that since the asset pipeline does it by default and according to my knowledge (which might be completely wrong) it would be really bad for performance. For the same reason I don't want to just go ahead and add
config.serve_static_assets = false
to my production.rb
since I don't want Rails serving static assets in production - I want Apache/nginx to do it.
How are you supposed to do this in Rails 4? Please help!
I finally managed to fix this issue. There are 2 parts to the solution. Firstly, you need to tell Rails to precompile images. As far as I can tell Rails (since 4.0) will no longer do this automatically to prevent gems you include from having all their assets precompiled when you don't really want this.
config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif)
Now your images should be getting precompiled (you can check this by running rake assets:precompile
and looking at the results in public/assets).
Now you need to change your JQuery UI theme to reference the fingerprinted images instead of the plain image URL. So change the theme's filename extension to .scss (in my case it was jquery-ui-1.10.4.custom.css.scss) and do a find and replace in your theme - changing url
to the SASS helper image-url
. So, as an example,
url(images/ui-bg_glass_65_ffffff_1x400.png)
becomes
image-url('images/ui-bg_glass_65_ffffff_1x400.png')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With