Custom field in devise without mass assignment
I am using devise for authentication but have also added a display_name
field that I don't want the user to be able to edit after creating
registration/sign up. The problem is unless I add this column/field with
attr_accessible in the model, I get the following error.
Can't mass-assign protected attributes: display_name
But I can't enable attr_accessible because that will open the app up to
mass assignment hack in through the edit method.
I thought about overriding Devise::RegistrationsController to supplement
devise's create method, as shown in this gist, but filtering the params
before calling super will obviously result in the display_name not being
saved at all, and the field would show up empty in a form after validation
fails for any reason.
Is there method I can override or a hook I can add into the model to
prevent mass assigment of a single variable in certain conditions? Perhaps
I can remove the display_name from the parameter list before_validation
and put it back after_validation, while also validating it with a
technique like this, and then doing a normal validation-less single
assignment? Of course this still wouldn't prevent a mass assignment hack
through the edit method, so I'd have to add a signature to params[:user]
hash in the create method, which would be checked before removing/adding
display_name from params when validating/updating the display_name
attribute by itself. This seems like a mess to me, is there a better way
to control mass assignment in the controller while using devise?
One approach that would be quick and dirty would be to override
Devise::RegistrationsController like I mentioned first and simply cut and
paste the original create method from the original devise
registrations_controller.rb source, and manually add/remove display_name
from params[:user] before and after the build_resource(sign_up_params)
call. Just before the save call, I'd also have to add display_name
individually to the model object and use single attribute validation
hackery mentioned above if I want validation on display_name to work. If I
update devise in the future this approach has a high probability of
breaking the create method, so I've ruled it out.
After typing out these various approaches I've realized I will probably
override the edit method in Devise::RegistrationsController and raise an
error if params[:user][:display_name] or any other attribute not in
attr_accessible is set. This sort of blacklist in multiple places approach
also rubs me the wrong way, it will be too easy to forget adding this to
new methods during future expansion, even if the blacklist is kept DRY in
a separate private method. Still, this appears to be the least convoluted
way.
Is there another approach worth trying?
No comments:
Post a Comment