Upgrading to Rails 4.0

I’m busy upgrading several apps to Rails 4.0. As is to be expected, there are a few gotchas here and there. Most are documented somewhere… deep in a changelog… mixed in with dozens of other things that probably won’t bite you.

I’ve been posting some of my notes along the journey. This particular post will serve as a central reference point, a table of contents of sorts, and will just contain links to other posts. I’ll try to keep it updated as I add new posts.


See the official Ruby on Rails article to start.

Models and datastores




Missing assets in Rails 4.0 (part 2)

In addition to the asset path changes covered in part 1, there are some changes in how processed asset files are exposed to web clients.

In this case, the problem shows up with asset files that are referenced by name without the md5 fingerprint. Previously, plain-named asset files were also exposed to the webserver. Now they don’t seem to be.

The most likely culprit here are files referenced from within a CSS file, such as:

1src: font-url('custom-webfont.eot');
3background: url('background.png');

In this case, you’ll need to use the asset_path helper like so:

1src: url('<%= asset_path('custom-webfont.eot') %>');
3background: url('<%= asset_path('background.png') %>');

You may need to rename your css file to enable ERB parsing, eg: design.css becomes design.css.erb.

Another possibility are hard-coded asset references in your view templates somewhere. Once again, change such references to use the asset_path helper.


Missing assets in Rails 4.0 (part 1)

The asset pipeline was introduced in Rails 3.1. It continues to exist in Rails 4 and has seen a number of changes.

In one key change, Sprockets (the brains behind the asset pipeline) now looks in fewer places for asset files.

In Rails 3, Sprockets looked in app/assets, lib/assets, and vendor/assets for assets. Importantly, this applied not only to your main app, but also to any asset-providing gems, such as font-awesome-rails.

In Rails 4, Sprockets only looks in app/assets (both in your app and in gems). If you have any assets that aren’t working properly (most likely fonts, images, or CSS files not loading), first check for updated versions of any gems.

If it’s your own gem or a gem that hasn’t been updated, it may be as simple as moving lib/assets or vendor/assets to app/assets.


Capistrano errors when upgrading an app to Rails 4.0

First, be sure you’re using Capistrano v2.15.4 or higher. There are some significant changes in Capistrano’s awareness of assets and how it manages precompilation.

Rails 4 changes how the asset manifest is handled. The manifest holds a list of all available assets. In Rails 3, this was generated as public/assets/manifest.yml. In Rails 4, it’s now a JSON file along with a fingerprint, eg: public/assets/manifest-9f745054f45f3f47968d59f1665c66be.json.

By itself, Rails handles this without any issue – including the upgrade from Rails 3.2 to 4.0.

However, Capistrano has some issues here which seem related to its attempt at intelligent cleanup of assets no longer being used.

If your upgrade to Rails 4 works the first time through, you’re probably fine. If there’s any kind of error, you may be left in a mixed up state that’s hard to recover from.

Two possible errors you may see from Capistrano.

1More than one asset manifest file was found in '/apps/some_app/shared/assets'.  If you are upgrading a Rails 3 application to Rails 4, follow these instructions: http://github.com/capistrano/capistrano/wiki/Upgrading-to-Rails-4#asset-pipeline
1lib/ruby/1.9.1/psych.rb:203:in `parse': (<unknown>): mapping values are not allowed in this context at line 1 column 6 (Psych::SyntaxError)

I found it easiest to login to the app server(s) and remove manifest*.{yml,json}.

Be warned, removing these files may make it difficult to rollback to a Rails 3.2 version of your app. In theory, you just need to rollback and then recompile the assets. In practice, I experienced some weird issues with bundler loading Rails 4 gems when it was supposed to be loading Rails 3.2 gems, making it impossible to regenerate the asset manifest. You may want to move those files aside instead of just removing them.

I ended up removing the current symlink along with the manifests which then allowed Rails 4 assets to finally build properly without any complaints from Capistrano:

1rm /apps/some_app/current /apps/some_app/shared/assets/manifest*.{yml,json}

You can remove current while the existing (Rails 3) app is still running. However, it’s possible assets will longer be served by your web frontend (apache, nginx, etc.) until the Rails 4 app successfully compiles assets and starts.

If you have any way of testing against a staging server (starting from the Rails 3.2 version of your app), I highly recommend it.

Also related:


Errors when precompiling assets in Rails 4.0

Rails 4 now always loads initializers and the database configuration before precompiling assets. Depending on your deployment environment, this may cause errors.

For example, not finding database.yml:

Could not load database configuration. No such file - /apps/some_app/releases/20130703220638/config/database.yml

In Rails 3, this was solved with:

1config.assets.initialize_on_precompile = false

However, this configuration option no longer exists in Rails 4. One workaround is to pass a dummy database init string to rake assets:precompile:


Be sure to replace postgresql with your database adapter name if using something other than Postgres.

A complete example:

1bundle exec rake RAILS_ENV=production DATABASE_URL=postgresql://user:pass@ assets:precompile

With Capistrano’s assets handling, you can just set :asset_env:

1set :asset_env, "RAILS_GROUPS=assets DATABASE_URL=postgresql://user:pass@"