Fairly new to rails so forgive me if I've misunderstood anything. I have a user model that looks like the below. Ideally what I'd like to do is have regular users only able to update their password, but have administrators able to change their username, email, etc...
class User < ActiveRecord::Base
# Default auths
attr_accessible :password, :password_confirmation, :remember_me
# Admin auths
attr_accessible :login, :username, :email, :password, :password_confirmation, :remember_me, :role_ids, :as => :admin
end
To update the record as an admin I do the following:
@user.update_attributes(params[:user], :as => :admin)
But lets say I want to update the user record as a non-admin:
@user.update_attributes(params[:user])
I receive the following exception:
ActiveModel::MassAssignmentSecurity::Error in UsersController#update
Can't mass-assign protected attributes: email, username
What I'd like to happen is for the non-accessible params to be ignored and for only accessible attributes to be update, whereas currently the whole update fails. Is this possible and more importantly is this the recommended way to do things? Would it be better to manually strip out the inaccessible parameters before calling update_attributes?
One thing you can do is set
config.active_record.mass_assignment_sanitizer = :logger
This will log the filtered attributes instead of throwing ActiveModel::MassAssignmentSecurity::Error
.
Alternatively, you can write your own sanitizer extending ActiveModel::MassAssignmentSecurity::Sanitizer
, customizing process_removed_attributes
to fail silently.
As for your other questions
... is this the recommended way to do things? Would it be better to manually strip out the inaccessible parameters before calling update_attributes?
I think you should be looking into why you're allowing a form to be submitted containing fields which will be rejected by Rails when submitted for some roles and not others. For example, it doesn't make sense to let a regular user see/change a Username
text field in the form if attr_accessible
for their role omits that attribute.
You should instead hide the non-admin fields for users who are not admins, and leave the :strict
sanitizer in place. The only time the ActiveModel::MassAssignmentSecurity::Error
would be raised is if someone was modifying the DOM, trying to submit fields which they were not provided and thus not allowed to modify for the related model.