sass-rails asset pipeline: generating image paths incorrectly; `url(/images/blah.png)` instead of `url(/assets/blah.png)` - ruby-on-rails

In section 2.2.2, "CSS and Sass", I'm told to put image-url('delete.png') in my sass. And so I have.
However, it is generating CSS like
background-image: url(/images/delete.png)
instead of the thing that I'm told everywhere it should be generating, the correct and obvious thing,
background-image: url(/assets/delete.png)
What. The heck.
I have spent literal days trying to figure out where this is coming from.
Here's a gist of relevant settings that are resulting in this behavior. Here's a gist of the same files in an earlier version of our code base (right after we implemented the asset pipeline and it actually worked for about a week before this frustrating behavior popped up). Can you spot the differences? Any other files you can think of that might be causing this?
Note
We're purposely using an older version of sass-rails because a newer version was causing Stack level too deep! errors when precompiling.
We're using Compass.
Two hackish attempts at workarounds
Because actually troubleshooting the asset pipeline kinda sucks.
1: Put images in /images
I attempted to just move all of the images to public/images and add that as a load path. This worked in dev (images are accessible at either /assets or /images), but precompiling for production puts the fingerprinted images in /assets only (obvs), so when sass-rails puts in url(/imagse/delete-120398471029384102364.png), it can't be found.
2: Make /public/images a symlink to /public/assets
This would probably work in production, but in development the /assets folder doesn't exist, so the url(/images/delete.png) directives result in unfound images.

If you do not have this already, name your css file *.css.scss (as opposed to .sass - if you do this, you might need to adjust the syntax of some statements). Then use the image_path helper instead of image-path, e.g.:
background-image:url(image_path('delete.png'));
I expect this to solve your issue. If it does not, what is the asset path generated by this approach for you?

This looks to be due to your version of sass-rails (3.1.0). I can reproduce your problem (thanks for posting the Gemfile) and it goes away when bumping to sass-rails 3.1.4.
Try upgrading to 3.1.4 and clearing tmp/cache. Also make sure you're not hitting any browser caches.
I know you said 3.1.4 was causing other problems... have you tried higher versions?

It really looks like this issue: https://github.com/rails/sass-rails/issues/57
If so you should try to find the good combination of versions between Compass and Sass-rails.
And maybe upgrade everything (Rails included) to latest versions, it's still the best way to do (use bundle outdated command in bundler 1.2 to know what Gems to upgrade)

This is our combo of haml-rails, compass and sass-rails. We're running rails 3.2.6 though.
This has worked well for us.
gem 'compass', git: 'git://github.com/chriseppstein/compass.git', ref: '3a4c5c75dca9f07f6edf2f0898a4626269e0ed62'
gem 'haml-rails', git: 'git://github.com/indirect/haml-rails.git', ref: '92c41db61f20a9f122de25bc73e5045cfccdbcd5'
gem 'sass-rails', '~> 3.2.5'

Not necessarily a solution, but certainly an available option: If you're open to using compass spriting, you'll cut down on the number of http requests and be able to manually specify your image path with a sprite map, ie '$sprites: sprite-map("PATH/*.png");'

Sanity check the file in your current asset pipepline. Check that it's in one of the directories listed in here:
<%= debug Rails.application.config.assets.paths %>
Next check at what relative path compass expects to find the image ( and see if it mat. According to the Compass config docs, one of these should tell you:
<%= debug config.compass.http_images_path %>
<%= debug config.compass.http_generated_images_path %>
I'm guessing it's the first one. Either way, compare their path to your image's asset_path:
<%= debug asset_path 'delete.png' %>
If the paths don't match, maybe you need to adjust the path in your environment configs (development.rb, ...) to this for example:
config.compass.http_images_path = '/assets.
Alternatively, you could move the image to where http_images_path or the http_generated_images_path expect to find it.
At the point, asset_path/asset_url (which are much less brittle than hardcoding) should hopefully work. I based this off of a similar technique I saw for stylesheets,

For me,
Changing image_path to image-path worked for .scss. Later on, I changed to image_path again and it's working fine now.
Deleting cache didnt help me.

After I edited my .scss file (added a space) and reload the page I got right result. After I removed the space it worked correctly.

Related

getting around the Gem::Package::TooLongFileName issue

I am trying to package a rails app as a gem. Part of what I want to put into the gem are the precompiled assets (so the user doesn't have to bother with that). However, gem build <my_gemspec> chokes on the super long file names of the digested precompiled files in public/assets. Anyone else been through this?
Thanks!
One other note: this isn't a gem that would be used by another application. Rather its a packaging of a standalone rails app. The gem makes it easier for people to use it by simply calling its executable to run.
I got around this problem by doing:
config.assets.configure do |env|
env.digest_class = Digest::MD5
end
which shortened the asset names enough while still maintaining a digest

How to tell Rails to not clean some assets in the public folder

The issue here is that I have Bootstrap on production looking for the fonts at:
assets/spree/fonts/glyphicons-the-file-name.something
When in development mode, it looks for these assets in:
fonts/glyphicons-the-file-name.something
So what I did was I added the fonts folder into public and it all worked. I did the same for production. You can guess that I'm now dealing with a rails assets:clean issue that must be running and removing the files, hence not allowing them to appear.
Is there a way to tell Rails to not clean the files in assets/spree/fonts?
I'm assuming you installed the bootstrap files manually?
If you instead use a gem such as the following, then you won't have to worry about these issues:
gem "bootstrap-sass"
Alternatively, you should be installing everything into your vendor directory. As you've found you'll then have issues with any linked assets within these files. The correct fix for this would be to edit the bootstrap source to use the correct asset_path helpers.
Obviously that's quite a bit of maintenance overhead when you get round to doing the next bootstrap update.
I'd take a look at the bootstrap-sass gem, even if you decide not to use it.

ERB not being imported by the asset pipeline

I have recently upgraded an old app to Ruby on Rails 3.2.9. While enabling the asset pipeline, I changed my css.scss files to css.scss.erb so that I could use the helpers to load only the fingerprinted image files, like this:
`background: url(<%= asset_path "wishlist.png" %>)`
This works on standalone files, but when the css.scss.erb file has to be imported by screen.css.scss, it returns the following error:
`Invalid CSS after "...d: url(": expected ")", was "<%= asset_path ..."
I tried all the suggestions presented on this question, but none of them avoids the error while making the app load the fingerprinted files.
Any solutions?
Thanks in advance.
The problem was that the sass-helpers provided on the Ruby on Rails Guide to the Asset Pipeline were using an hyphen instead of an underscore. Change everything to image_path instead of image-path (and so on) and it should work fine, like on this:
background: url(image_path("wishlist.png"));
It is not a direct solution but if you are using sass-rails then you could use asset-path helper provided by it, like described here
Try giving this link a shot:
http://guides.rubyonrails.org/asset_pipeline.html
Also you should check if your gems are updated.
Try adding "load 'deploy/assets'" to your Capfile (without the quotes)
If none of the above works, try turning off the debug on your develop env:
config.assets.debug = false (do that on your environments/development.rb)
That way you could try to inspect the code more freely without the need of deploying
Hope any of this helps. Share the results when the issues is solved! ;)

Rails 3.1 .css.less caching error

I am quite new with Rails and I am having some irritating problems with caching of css files.
I have a .css.less file with imports inside it. It's the only stylesheet the app includes, so the other files get imported only once and by this unique stylesheet.
One of those imported .css.less stylesheets seems to be cached somewhere, because does not change in the browser when I change it's source.
I can only see the changes I made if I change something in the root stylesheet.
I have the server in development mode, so the caching should be off. I have also used <%= stylesheet_include_tag "style", :cache => false %>
I tried with Chrome and Firefox, with and without clearing their cache too. Always the same result, if I work only on that file the css the page receives when reloaded doesn't have the changes...
I also stopped the server and rm everything in the tmp folder of the app. No changes.
I am using Rails 3.1 with Ruby 1.9.3, with the less-bootstrap-rails gem. Both the root stylesheet and the imported one have .css.less extension.
What am I missing?
Thank you!
This is an area where I think the asset pipeline is broken, but I don't think there's a good fix.
If I remember correctly, to get changes in files you've included/required in your .css.less file, you need to change the .css.less file itself.
I had this on Rails 4.0.8, infuriating. The config changes mentioned above didn't help. Here's what seems to have fixed it for me:
Ensure NO FILES share a base name. For example, you have a reports.css.less and a reports.js.coffee? Doesn't matter if they're in the same directory or not. Rename or delete one of them. (I changed it to reports-styles.css.less).
Blow away your cache: rm -rf tmp/cache
Restart your Rails app.
This appears to be a decent fix but, since I don't know what's actually going on, this could be totally false and it's just working by coincidence now. Sorry this answer isn't more rigorous!
I've just came across the exact same problem.
I found that if you rename your *.css.less file (the one with the imports inside) to *.less, then this weird cacheing problem gets resolved.
Add this to your config/application.rb
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
See more at: Ruby on Rails Guide: Asset Pipeline

Rails 3.1 and Image Assets

I have put all my images for my admin theme in the assets folder within a folder called admin. Then I link to it like normal ie.
# Ruby
image_tag "admin/file.jpg" .....
#CSS
.logo{ background:url('/assets/images/admin/logo.png');
FYI. Just for testing I am not using the asset_path tag just yet as I have not compiled my assets.
Ok all good so far until I decided to update an image. I replaced some colors but on reload the new styled image is not showing. If I view the image directly in the browser its still showing the old image. Going one step further I destroyed the admin images folder. But it has broken nothing all the images are still being displayed. And yes I have cleared my cache and have tried on multiple browsers.
Is there some sort of image caching going on? This is just local development using pow to serve the pages.
Even destroying the whole images folder the images are still being served.
Am I missing something?
In 3.1 you just get rid of the 'images' part of the path. So an image that lives in /assets/images/example.png will actually be accessible in a get request at this url - /assets/example.png
Because the assets/images folder gets generated along with a new 3.1 app, this is the convention that they probably want you to follow. I think that's where image_tag will look for it, but I haven't tested that yet.
Also, during the RailsConf keynote, I remember D2h saying the the public folder should not have much in it anymore, mostly just error pages and a favicon.
You'll want to change the extension of your css file from .css.scss to .css.scss.erb and do:
background-image:url(<%=asset_path "admin/logo.png"%>);
You may need to do a "hard refresh" to see changes. CMD+SHIFT+R on OSX browsers.
In production, make sure
rm -rf public/assets
bundle exec rake assets:precompile RAILS_ENV=production
happens upon deployment.
For what it's worth, when I did this I found that no folder should be include in the path in the css file. For instance if I have app/assets/images/example.png, and I put this in my css file...
div.example { background: url('example.png'); }
... then somehow it magically works. I figured this out by running the rake assets:precompile task, which just sucks everything out of all your load paths and dumps it in a junk drawer folder: public/assets. That's ironic, IMO...
In any case this means you don't need to put any folder paths, everything in your assets folders will all end up living in one huge directory. How this system resolves file name conflicts is unclear, you may need to be careful about that.
Kind of frustrating there aren't better docs out there for this big of a change.
In rails 4 you can now use a css and sass helper image-url:
div.logo {background-image: image-url("logo.png");}
If your background images aren't showing up consider looking at how you're referencing them in your stylesheets.
when referencing images in CSS or in an IMG tag, use image-name.jpg
while the image is really located under ./assets/images/image-name.jpg
http://railscasts.com/episodes/279-understanding-the-asset-pipeline
This railscast (Rails Tutorial video on asset pipeline) helps a lot to explain the paths in assets pipeline as well. I found it pretty useful, and actually watched it a few times.
The solution I chose is #Lee McAlilly's above, but this railscast helped me to understand why it works. Hope it helps!
The asset pipeline in rails offers a method for this exact thing.
You simply add image_path('image filename') to your css or scss file and rails takes care of everything. For example:
.logo{ background:url(image_path('admin/logo.png'));
(note that it works just like in a .erb view, and you don't use "/assets" or "/assets/images" in the path)
Rails also offers other helper methods, and there's another answer here: How do I use reference images in Sass when using Rails 3.1?

Resources