What is mass-assignment in Rails 3

Bhushan Lodha picture Bhushan Lodha · Aug 3, 2012 · Viewed 10.7k times · Source

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?

Answer

meager picture meager · Aug 3, 2012

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:

  • You have an attr_accessible declaration which does not include :name
  • You have an 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.