Strong parameters and attr_accessible
are two different ways of adding security protections to the Rails "mass assignment" feature. Strong Parameters is the way that is prescribed by the current version of Rails.
"Mass assignment" is a convenient shorthand in Rails that allows you to set many properties of a model in a single statement.
For example, imagine you have a @user
that you want to update with data from a form submission. Without mass assignment, you'd have to write tedious code like this:
@user.first_name = params[:user][:first_name]
@user.last_name = params[:user][:last_name]
@user.phone_number = params[:user][:phone_number]
...
@user.save
And on and on for every form field.
With mass assignment, all of that code becomes a single line:
@user.update(params[:user])
But, this is full of security holes. Since params
contains whatever data was submitted by the browser, a malicious user could add data to that submission that you did not expect. For example, they could add is_admin=1
to the parameters. If you have an is_admin
database column, then mass assignment just let the user upgrade to an administrator. Yikes!
This is where Strong Parameters comes in. With Strong Parameters, Rails will raise a ActiveModel::ForbiddenAttributesError
if you try to do the naïve update(params[:user])
. Instead, you need to be explicit about what parameters you expect from the browser submission, using the require
and permit
helpers that Strong Parameters provides. Like this:
def user_params
# Note that :is_admin is not permitted!
params.require(:user).permit(:first_name, :last_name, :phone_number)
end
...
@user.update(user_params)
I can't speak for the maintainers of Rails, but I like Strong Parameters because it is flexible. If I have multiple actions in the users controller that expect different parameters, I can easily describe using permit
the parameters that should be allowed.
Or if I have different user roles that are allowed to update different attributes, then I can easily model those permissions. As @CV-Gate mentioned, you can even change these permissions at runtime, which is a powerful.
In short, the flexibility of Strong Parameters is due to the fact that you can define that user_params
method anywhere, and however you like. You have the full power of Ruby and OO concepts to make it work the way you want.
What about attr_accessible
?
Without going into too much detail (since this feature is no longer supported by Rails): instead of using the permit
method, you would do something similar using an attr_accessible
macro in the model itself, like this:
class User < ActiveRecord::Base
attr_accessible :first_name, :last_name, :phone_number
...
end
So for simple cases, it works very similar to Strong Parameters; you just define the list of attributes in a different place.
However, since attr_accessible
is strongly coupled with the definition of the model class, you lose a lot of flexibility. What if you have two different controller actions that need to do mass assignment for the same User
model? Now you are stuck.
attr_accessor
The attr_accessor
macro is built into Ruby and has nothing to do with Rails, mass assignment, or security. It just happens to have a similar name. :)