I have heard couple of people complaining and posting questions about mass-assignment in Rails. I have got same error couple of times and all I did was attr_accessible
. But what exactly is mass assignment? could somebody explain with example?
Mass Assignment is the name Rails gives to the act of constructing your object with a parameters hash. It is "mass assignment" in that you are assigning multiple values to attributes via a single assignment operator.
The following snippets perform mass assignment of the name
and topic
attribute of the Post
model:
Post.new(:name => "John", :topic => "Something")
Post.create(:name => "John", :topic => "Something")
Post.update_attributes(:name => "John", :topic => "Something")
In order for this to work, your model must allow mass assignments for each attribute in the hash you're passing in.
There are two situations in which this will fail:
attr_accessible
declaration which does not include :name
attr_protected
which does include :name
It recently became the default that attributes had to be manually white-listed via a attr_accessible
in order for mass assignment to succeed. Prior to this, the default was for attributes to be assignable unless they were explicitly black-listed attr_protected
or any other attribute was white-listed with attr_acessible.
It is important to consider which attributes can be mass assigned because code like this is so common:
@post = Post.new(params[:post])
Typically this is used when the user submits a form rendered by a form_for @post
. In an ideal world, the params[:post]
hash should only contain the fields we displayed on the form. However, it is trivial easy for the user to pass additional fields in their request, so in effect you're allowing a user to set any fields on @post
, not just the ones displayed on the form.
Failure to safely use mass assignment has led to several high profile bugs in some pretty big Rails applications, like the one that allowed somebody to inject their own public key into the list of trusted keys on a Github repository and push code directly to a repository they should not have had access to.