Mass assignment is a feature of Rails provided for using less code for updating a model like this
Model.create(params[:model])
@model.update_parameters(params[:model])
instead of
@model.field1 = params[:model][:field1]
@model.field2 = params[:model][:field2]
...
@model.save
But with this feature, comes the risk of updating values which we dont intend. For example, if we want just field1, field2 and field3 to be updated by the user and you use update_parameters
for mass assignment, there is a risk of updating field4, if one is passing model[user][field4]=some_value
either from url or by any other ways. If we are explicitly assigning the fields in the code, we do not have this risk. But then we will have to set the values for each field(wherever we are updating or creating) which is not very productive.
So, for using the mass assignment feature, we have 2 options. First is attr_protected
attr_protected :field4
This will protect field4 from being saved from mass assignment from params[:model] even if it contains field4. For saving field4, we have to call the setter for field4 explicitly in
the code(@model.field4 =
). But, the problem with attr_protected
is that Rails may provide some other attributes that we may not know for mass assignment. For example, if we define
has_many :model2s
in Model.rb, Rails will provide a method model2_ids=
automatically and this can be accessed by mass assignment.(If we give model[model2_ids]=
in the url, it will create associations, not intended at all). So, there is a chance of missing attributes like this while using attr_protected
.
So, the recommended method is to use attr_accessible
attr_accessible :field1, :field2, :field3
This will make these fields open for mass assignment and all other attributes in the model not available for mass assignment. So, the recommended way is to make those attributes which we are providing in a form for users to edit as attr_accessible
and all other parameters will be protected. But, while using this you have to make sure you have included all the attributes you need for edit as attr_accessible
.
In your case, since you want the user to edit the role_ids
and you are providing access to CRUD for admin users only, I think you can use attr_accessible :role_ids
. The alternative would be to assign role_ids
explictely like .role_ids = params[:user][:role_ids]
. You should use this, if you have another form where you dont want the user to edit the role_ids.