I have just been doing a bit of reading on attr_accessor
, attr_accessible
and strong parameters at a few different locations:
Difference between attr_accessor and attr_accessible
How is attr_accessible used in Rails 4?
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
And I am looking at mass assignment:
http://code.tutsplus.com/tutorials/mass-assignment-rails-and-you--net-31695
I can't get my head around the difference between attr_accessible
and strong parameters. I am not 100% confident in my understanding of the subjects mentioned above so I could be missing something simple but I know they do a similar job.
However, what is the difference between attr_accessible
and strong parameters? Are they just a different name for the same thing? Why did we move from one to the other?
Any info is appreciated.
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. :)
attr_accessible has been deprecated in Rails 4 in favor of Strong Parameters.
Both are different approaches to the mass assignment problem but Strong Parameters is more flexible.
In example, you have an User
model with the attributes email:string
and is_admin:boolean
. You wish to allow the users to modify their email through a form but not the is_admin
field.
In Rails 3 you should do:
attr_accesible :email
With this approach it's not possible for an user to modify is_admin
because that attribute is protected.
One of the good things of Strong Parameters is that you could do the following in your controller:
def user_params
if current_user.admin?
params.require(:user).permit(:email, :is_admin)
else
params.require(:user).permit(:email)
end
end
This way one admin user will be able to modify is_admin
while a normal user won't.
This is just one example and not the best way to grant administrative permissions to an user but it's quite illustrative.
The main advantage of Strong Parameters is that they are defined in the controller and can be dynamically assigned in run time. attr_accessible was a more static and monolithic way to whitelist attributes.
On the other hand attr_accessor is completely different thing and still can be used in Rails 4, in example, if you need one attribute in your model that it's not necessary to persist or to be written into the database but you require it in a form. Think about:
attr_accessor :has_accepted_legal_terms
It's a Ruby method that can be used to declare an attribute of your model that is not related to the database, an attribute of a Class or PORO (plain old ruby object).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With