Devise model custom field updates with Rails

Devise gem helps in creating User Authentication layer for the Ruby on Rails applications. The other day, I was taking a session on Hackhands to resolve a query from a Ruby on Rails developer. The developer had added an enum attribute role on the users table. The query was how to update custom attribute added to users table generated by devise gem.

Intuition

The intuition was that, RegistrationsController inbuilt with Devise will automatically handle the updates to the fields if parameters are sent out correctly. We will discuss how to add and update custom fields to the users table generated by devise.

But, that’s not how update action written inside devise gem works. The update action considers only the parameters that are created by the devise gem by default.

Override update parameters

Devise uses devise_parameter_sanitizer helper to sanitize the input parameters. To pass the custom parameters devise suggest to override the parameters that are passed for an update or for any devise controller specific action.

Strong parameters in controller

Devise gem uses the code given below to fetch account_update_params

def account_update_params
  devise_parameter_sanitizer.sanitize(:account_update)
end

This calls in devise_parameter_sanitizer to make sure the code uses strong_parameters. To have the new attributes for account update, we should not override account_update_params method. Instead we should use devise_parameter_sanitizer to sanitize the inbuilt parameters and extra parameters that we want.

# Set up a param sanitizer to filter parameters using strong_parameters. See
# lib/devise/parameter_sanitizer.rb for more info. Override this
# method in your application controller to use your own parameter sanitizer.
def devise_parameter_sanitizer
  @devise_parameter_sanitizer ||= Devise::ParameterSanitizer.new(resource_class, resource_name, params)
end

We can see how the devise_parameter_sanitizer sanitizes the parameters that are passed for an update action.

Devise Parameter Sanitizer

The Devise guide suggests how to permit the subscribe_newsletter parameter for sign_up action.

class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
  # Permit the `subscribe_newsletter` parameter along with the other
  # sign up parameters.
  devise_parameter_sanitizer.permit(:sign_up, keys: [:subscribe_newsletter])
  end
end

For permit method parameters are as given below.

  • First parameter defines an action to be called. Use :account_update for an update action.
  • Second parameter defines keys to be whitelisted and passed in for the action defined in first parameter.

Conclusion

Devise suggests to override the method in ApplicationController. Better would be to override the Devise::RegistrationsController and then override the devise_parameter_sanitizer method in the RegistrationsController that you define. This is how we can update custom fields in devise generated users table.

In general, override the method defined by devise in a way to whitelist the parameters that are required for the logic of the required action.