Sometimes the asset pipeline isn't flexible enough
In my latest application, I wanted to display full-width and full-height background images randomly from some web source.
I couldn't find any documentation about how to call a background image from a URL - and it's true that these things change over time and one day my application my hit a 404. So I ended up putting 9 images that I liked (and own the rights to) in my assets/images folder, precompiling and pushing the application live.
The code for the randomization is like this:
I put this in my layout file - application.html.erb. Normally you wouldn't include CSS definitions like this directly in the html file - you put them in a css/scss/sass file.
But here we have a learning opportunity - we want to call a helper method that we defined called 'randomized_background_image' and we need to call it using ERB syntax so that it will be interpreted.
I couldn't think of a better way to do it directly in the CSS file (and I found most of what I needed on Stack Overflow, so I left it alone). I have a definition inside my primary CSS file in case this override ever chokes, but this helper method goes to Application Helper and is defined like so:
module ApplicationHelper def randomized_background_image images = [ ("/assets/bg0.jpg"), ("/assets/bg1.jpg"), ("/assets/bg2.jpg"), ("/assets/bg3.jpg"), ("/assets/bg4.jpg"), ("/assets/bg5.jpg"), ("/assets/bg6.jpg"), ("/assets/bg7.jpg"), ("/assets/bg8.jpg") ] images[rand(images.size)] end end
Pushing this out - you have a nice random image effect for the background of your site or app.
Now there is a problem - which is the namesake of this post - there is no way that I could find to make those assets actually come from my defined asset site.
I use Amazon CloudFront in most of my projects, and I end up with a convention of:
http://cdn0.hostname.com
http://cdn1.hostname.com
http://cdn2.hostname.com
And so on through 9. This allows us to skirt the limitation of a browser only opening a max of two simultaneous connections to a host. When we want to serve lots of css, js, and image files concurrently (and quickly), we make sure to fake a bunch of random hostnames (which all go back to the same CloudFront URL of course) in order to get those things moving across the inter-tubes.
So back to our problem - normally from a view you can call:
<%= image_tag "bg" %>
and rails will automagically figure things out for you - grab the image from either your public/assets directory or from your /assets directory if you have the fallback option enabled (disable it in production please).
In your CSS files, you might have used something like:
background-image: url('image.jpg');
In order to serve these assets through the asset pipeline.
But what if you are in my shoes? You want to serve the assets through the asset pipeline from a Class?
The asset helper tags weren't really meant for that.
I tried solutions like the following:
``` default ActionController::Base.helpers.image_path("/assets/bg0.jpg")