Rails 5
Rails 5: The Sprockets 4 Manifest
When Rails 5 is released it will require that you upgrade to Sprockets 4. Sprockets 4 has some big changes in how it knows what assets to compile so you will definitely have some updates to make if you rely on Sprockets within Rails. Since there are a lot of changes in Sprockets 4 I’ll just be talking about the new manifest.js
in this post.
With Sprockets you used to tell your config/initializers/assets.rb
what assets were supposed to be precompiled. In Sprockets 4 you will use a manifest.js
inside your app/assets/
directory to tell Sprockets what assets to precompile. This behavior is actually available to use in Sprockets 3 but sprockets-rails has a conditional that only activates this in Sprockets 4.
Note: the file type that manifest.js
is stored as may change. There is disucssion around moving the manifest.js
to manifest.yml
because it doesn’t make sense that the manifest has a file type that is unrelated to it’s usage.
So, how do you use a the new manifest file? In your app/assets/
directory add a new directory named config/
. Inside that folder add a file called manifest.js
.
In the manifest.js
you’ll want to link your JS and CSS directories as well as any other directories you rely on like images, fonts, sounds etc.
Here is an example of a manifest.js
that links JS, CSS, fonts, and images.
Previously you didn’t need to include fonts and images in your precompiled assets list and Sprockets Rails would use the LOOSE_APP_ASSETS
constant to figure out those items, but now you have to explicitly include them in your config.
You’ll notice that we use link_directory
for CSS and JS, then the path from the config manifest file to the javascript “file”. We compile .coffee
and .scss
down to .js
and .css
, respectively, so we denote that after the path to the JS and CSS files to tell Sprockets what to compile them into. Images and fonts don’t change file type when compiled.
Once you’ve done that you’ll need to remove config.assets.precompile
from your config/initializers/assets.rb
.
Smaller apps may only have the precompile
directive in their applications so in that case you can delete the config/initializers/assets.rb
file. For larger apps, like Basecamp we have some extra settings regarding assets and didn’t want to delete the config file.
Rails 5: ActionController::Parameters Now Returns an Object Instead of a Hash
A big change coming is how ActionController::Parameters
works. ActionController::Parameters
is where all of your params
come from for your controllers. Calling params
used to return a hash, but now will return an object.
Note: this doesn’t affect accessing the keys in the params hash like params[:id]
. You can view the PR that implemented this change here: https://github.com/rails/rails/pull/20868
To access the parameters in the object you can add #to_h
to the parameters:
If those params aren’t explictly permitted you will be returned a hash with only the permitted parameters. If none are permitted you’ll get an empy hash ({}
). This comes in where you may be running #symbolize_keys
or #slice
on unpermitted params
. If you’re accessing params
that aren’t being saved to a model/db then you probably aren’t explictly permitting those parameters.
If we look at the #to_h
method in ActionController::Parameters
we can see it checks if the parameters are permitted before converting them to a hash.
Let’s take an example where we are slicing params to use later. If we have this method that slices params we used to be able to write:
Which would return:
But now that will return an ActionController::Parameters
object.
Calling #to_h
on this would return an empty hash because param_1
and param_2
aren’t permitted.
To get access to the params from ActionController::Parameters
you need to first permit the params and then call #to_h
on the object. The following returns the same thing as slice did previously.
Another way to do this would be to use #to_unsafe_hash
if you know the params are not user supplied and are safe:
By default controller
and action
parameters are allowed. To explicitly always allow other parameters you can set a configuration option in your application.rb
that allows those parameters. Note: this will return the hash with string keys, not symbol keys.
Config option:
Calling slice on the parameters:
If you’re not sure when you’ll have time to upgrade it would be a good idea to write some tests for your controllers that access the params
. That way when you do upgrade you’ll know to fix the params because your tests will be failing.