One of the new features in Rails 4.0 is “Strong Parameters” (a gem) which moves mass assignment out of the model and into the controller.
Mass assignment allows multiple attributes of a class to be assigned simultanteously upon instantiation.
Sometimes you don’t want all attributes to be mass assign-able. To provide mass assignment protection, you can specify which attributes can be mass assigned using “attr_accessible” in the model.
class User < ActiveRecord::Base attr_accessible :name, :email end
If you want to mass assign different attributes for different roles, you would specify what is attr_accessible for each role.
class User < ActiveRecord::Base attr_accessible :name, :email # default role attr_accessible :eat_cake, :as => :admin # admin role end
There has been a lot of discussion within the community about whether mass assignment security belongs in the model layer. If an application has complex authorization requirements, adding separate code for each “role” can become cumbersome. Since the controller handles the flow between user and application including the authentication and authorization, it seems reasonable to move mass assignment protection into the controller.
DHH built the Strong Parameters gem to address this issue and as I mentioned at the beginning of the post, this feature is integrated in Rails 4.0 by default. Below is an example of how it could be implemented.
class UsersController < ApplicationController def update user = User.find(params[:id]) if user.update_attributes(user_params) redirect_to home_path else render :edit end end private def user_params params.require(:user).permit(:name, :email) end end
The ‘require’ method ensures that the specified key is available in the params hash and the ‘permit’ method specifies which attributes can be mass assigned.
To implement the mass assignment protection in the controller in Rails 3.2.x, you would need to install and require the Strong Parameters gem and then add the following code in addition to the code above:
In the config/application.rb file:
config.active_record.whitelist_attributes = false
or just remove the code completely.
In the model:
class User < ActiveRecord::Base include ActiveModel::ForbiddenAttributesProtection end