Ruby on Rails, programming, and SEO
Check out my articles about Ruby on Rails, programming, and SEO. Weekly updates? Subscribe to my feed.

Mass-assigning protected attributes in Rails

How to mass-assign to protected attributes in Ruby on Rails.

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

class User < ActiveRecord:Base
  attr_protected :account_id
end

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 => "Lasse", :email => "lassebunk@gmail.com")

or what’s used more:

User.create(params[:user])

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 called guard_protected_attributes which has a default value of true.

Example:

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

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, and update_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.

You can download the extensions here.

Follow me on Twitter

Related posts

Tags: , ,

Leave a comment

Fork me on GitHub