Strong Parameters in Rails 3
07 Oct 2013
For the uninitiated, Strong Parameters is a gem for white-listing attributes that can be mass assigned. This is a replacement for the Rails method of white-listing that ships in 3.x. It also ships standard in Rails 4, so it behooves you to be familiar with it. Herein, I will discuss a few lessons in switch an existing Rails 3 project over to Strong Parameters.
Like many things in the Rails world, Ryan Bates has already created a Railscast on Strong Parameters. Writing on Ruby/Rails often seems like the South Park episode Simpsons Already Did It . Bates already did it. I won’t reiterate too much of what he covered and will instead try to build on it.
Strong Parameters Model
In the Railscast, Bates proposes a separate model for a permitted parameters object and then memoizing an instance within the Application controller. I agree completely with this design pattern, with two additions. One, I do not believe that you should use the model because you are looking to DRY up your API controller and regular controller usages. With strong parameters we are trying to be especially conscious of what attributes are allowed, therefore we should be explicit (verbose) in what is allowed. Second, you can add a bit of syntactic sugar to the model. There is a redundant structure in his original implementation where you have a method named after the model say
user which calls another method called
user_attributes which is just an array of attributes. Instead, I created a
method_missing so that I could remove the original (“user”) call. Within
method_missing I check if
user_attributes exists, and if it does, the model responds to
user and permits the attributes. A small change, but it can DRY up the model a bit.
Strong Parameters and Nested Forms
One of the more perplexing situations I ran across during the migration, was the issue of a Nested form. With a nested form you will see the following in your submitted params:
where item/items is your nested form. I wasn’t quite sure how to handle this situation because I was relying solely on the github documentation on SP. This documentation covers how to white-list nested attributes. But this case is special, the nested attributes are dynamic. We are not quite sure how many nested forms might be included in the params, and even it we did, it seems silly to white list these numbered values. I actually hacked out a solution to work around this “problem”, before I found how this should actually be done. You must place
accepts_nested_attributes_for in the model that will have the attributes nested in it. An example is found in the Rails 4 documentation.
Integration with CanCan
Another rub with Strong Parameters is when also using CanCan for authorization. You will run into SP mass assignment errors on the
create action if you use
load_and_authorize_resource. This occurs because CanCan tries to setup the proper model before it even enters the method defined in the controller. Of course, this is done through mass assignment, so you never get the chance to permit the params before hand. You have two solutions to this problem:
- You can setup a custom
before_filterthat permits the parameters before the
- You can except the
load_and_authorize_resouceand do the authorization inside of your method definition after param permitting.