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.
Related posts
Tags: Attributes, Mass-assignment, Ruby on Rails