Start loving assets pipeline and rails 4

Rails 4 handles assets a bit differently from the previous versions. Now for compiling the assets correctly you have to type it like this:

RAILS_ENV=production rake assets:precompile
Which means you have to define the rails environment. You also have to do it to some other services as well (for example if you type sidekiq without defining the environment, then you will run it in development and you may questioning yourself why you don't receive some background emails... real story).

So, you typed the above command, you didn't get any error, you are typing rails s -e production locally but you still don't see the assets. You are checking the public/assets folder and you see that the assets are there (if not, check below for troubleshooting). Why you don't see them then? Well, in Rails 4, the default behavior in production is your assets to be served by the powerful nginx or apache instead of the application server (webrick, puma, unicorn, passenger etc.). That's a good practice rails is the best framework and is thinking for you before you.

So, were is the place that it is defined this so you may want to change it (and serve the assets from the application server, as it happens in development)? It is in the config/environments/production.rb file and the parameter is the config.serve_static_assets = false. Now is a good time to take a look at this file and learn the rest configurations that you aren't familiar with. Just google them .

Well to check and see that the assets are served correctly in production, you can either change the above parameter to true or run nginx/apache with an application server. The easiest way for the second option is to install passenger and let him do it. Just type passenger start -e production and it will automatically compile nginx for you, start it and serve the assets as it should be in the production. So you don't have to change it and risk the chance of forgeting it when you are deploying your app (and yes that's another reason why I love passenger). Of course all of the above are the best practices for just checking / debugging locally, in a real production environment you should be configure it a bit as Ryan and many others suggests.


Public assets folder doesn't contain what I want

Ok I am hearing you saying that you did rake assets:precompile, you checked the public/assets folder and you didn't see your compiled .css, .js or images in there. What happened? I feel your pain. Well, there are the following problems that you may have:
You didn't use the default manifests application.css or application.js as a result your css/js aren't defined in the assets path. The rails app doesn't know where they are your custom manifests to compile them. There are two solutions for this. One is to use the application.css / application.js and define inside there your custom css/js as below:
For CSS:
// application.css.scss
@import "admin/bootstrap.min";
@import "your_custom_css";

For js (if it is in coffee):
# application.js.coffee
#= require jquery
#= require jquery_ujs

or if it is in plain js:
// application.js
//= require jquery
//= require jquery_ujs

and now you will have them compiled correctly. But wait you say! I don't want all my CSS to be loaded with the application.css (only one manifest) every time and once and for all, I have a front and a admin section (or better, more manifests, or whatever) and I want to serve them differently and separated. Ok you are right, so you have two solutions again (I know this post is going to be forever if I continue like that!).

One is to just put it in a folder, for example admin and name it application.css and for the front use another folder with a name front (or whatever you want) and name it again application.css inside there. And you are done, the admin css and js will be in there. you can take a look of a project defined like this here (which is the code of this blog btw).
The other solution is to add it in the assets path and define your custom css and js manually. How do you do that? I am glad you ask. Go to config/application.rb and add something like the following:

config.assets.precompile += ["front.css", "admin.css", "*.js]
inside the
class Application < Rails::Application
...
end

Also be careful that you can't just add in the config.assets.precompile the *.scss or *.sass because it will try to compile every scss one by one and it will throw compilation errors. Better try with the import so you don't have that kind of problems. SCSS is meant to compile altogether because they may have dependencies between the files.

Nice but what about images? I am getting balloons in there also. So, the most common problem with the images is that you haven't define it correctly inside your CSS, js or html. You can't just throw something like the following:

<img src="/assets/get_lucky.png" />
or 
background: url("assets/get_lucky.png");
put the get_lucky.png image inside the assets folder and wait to work on production. It will work in development but there is the pipeline! In the production the image name will be altered and the app should be aware of that.
You have to do it the rails way. How? Well for html:
<%= image_tag "get_lucky.png", alt: "I love text browsers" %>
For inside the css, if you are using scss (you should):
background: image-url("get_lucky.png");
or
background: image-path("get_lucky.png");
Or if you don't use scss do it like this:
background: url(<%= asset_url("get_lucky.png"));
or
background: url(<%= asset_path("get_lucky.png"));
There is another way like the following:
background: asset-url("get_lucky.png", image);
or
background: asset-path("get_lucky.png", image);
Ok there are much more details in all of the above but I feel like I am repeating what there is already in the great rails guides. So go check it there. It also contains useful information how to add nginx or apache configurations for assets in production, don't miss it!

comments powered by Disqus