“Mass-assigning protected attributes in Rails”

rails, Uncategorized

Rails has a great feature called protected attributes which you can set like this:

class User < ActiveRecord:Base
  attr_protected :account_id

Or you can use the inverted versions (which I prefer) where you set which attributes are accessible, like this:

attr_accessible :name, :email

What this does is that it tells Rails which attributes can be used in mass-assignment like this:

User.create(:name => "Piyush", :email => "mba.piyushgupta@gmail.com")

or what’s used more:


Then some malicious hacker cannot use mass-assignment to manually set the account_id.

If you try to assign to protected attributes you’ll get the following warning:

WARNING: Can't mass-assign these protected attributes: account_id

But the problem is: What if I’m no hacker, but I should have unlimited access, for example as an administrator? Then I can’t mass-assign to any protected attributes. Then I’d need to do something like this:

u = User.new(params[:user])
u.account_id = params[:user][:account_id]

Not very pretty.

What I’ve done is that I’ve created an extension to some of the methods taking mass-assignment and added an optional parameter calledguard_protected_attributes which has a default value of true.


# config/initializers/unprotected_attributes.rb
class ActiveRecord::Base
  def update_attributes_with_unprotected(attributes, guard_protected_attributes = true)
    send :attributes=, attributes, guard_protected_attributes
  alias_method_chain :update_attributes, :unprotected

We can do this because the native ActiveRecord::Base#attributes= can also be called with guard_unprotected_attributes.

Now you can call update_attributes like this:

user = User.find(3)
user.update_attributes(params[:user], false)

and it will also assign the protected attributes.

I have made extensions to create, new, update_attributes, andupdate_attributes!.

The ugly part, however, is that to make it work, I had to copy the functions in their entirety which could potentially mean that if you use it on a Rails version other than exactly 2.3.8 it might not work. Sorry for that.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s