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?