Adding Custom Fields to Your Devise User Model in Rails 4

I am currently working with Rails 4 and Devise 3.2.2. Devise already creates all the routes and controllers for allowing users to sign up, but as with most applications I want to customize the user model and add additional fields. Let’s take a look at how we would go about making these changes by adding a first and last name to the user.

First off, we create the migration – nothing special here.

class AddFieldsToUsers < ActiveRecord::Migration
  def change
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string
  end
end

Now we actually need to show these fields on the edit form - we can do this by adding a view to app/views/devise/registrations/new.html.slim (I’m using slim as my templating engine, you can use haml or erb or whatever you choose). I usually open the devise gem (bundle open devise) and then copy the devise view into my application and modify it.

h2 Sign up

= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
  = devise_error_messages!
  
  div
    = f.label :first_name
    br
    = f.text_field :first_name, autofocus: true

  div
    = f.label :last_name
    br
    = f.text_field :last_name

  div
    = f.label :email
    br
    = f.email_field :email

  div
    = f.label :password
    br
    = f.password_field :password

  div
    = f.label :password_confirmation
    br
    = f.password_field :password_confirmation

  div
    = f.submit 'Sign up'

= render 'devise/shared/links'

When you now try and sign up you should see the new custom form, but your custom fields will not be persisted. In Rails 3 we would need to add these fields to attr_accessor - which has been deprecated in Rails 4. Instead we need to customize the strong parameters for the devise controller action.

Customizing the RegistrationsController

If you do some digging through the devise gem you will find the code you care about in the registrations controller. Specifically, when we create an account this method is used to sanitize the parameters:

def sign_up_params
  devise_parameter_sanitizer.sanitize(:sign_up)
end

Similarly, when we update a user’s account this method is used to sanitize the parameters:

def account_update_params
  devise_parameter_sanitizer.sanitize(:account_update)
end

One solution would be to write and register your own sanitizer. I’m not a huge fan of this approach since it seems rather complicated and because you need to override Devise’s sanitizer in the application controller. A much simpler approach (in my opinion) is to simply override these 2 methods and specify the strong parameters directly.

We can do this by creating our own registrations controller (which extends Devise) and then customizing these methods as we choose.

class RegistrationsController < Devise::RegistrationsController

  private

  def sign_up_params
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
  end

  def account_update_params
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password)
  end
end

Here I’m customizing both methods since I want users to be able to specify their first and last names both when signing up and when updating their profiles.

Now we need to tell Devise to use our registrations controller - we can do this in our config/routes.rb file.

devise_for :users, :controllers => { registrations: 'registrations' }

That’s all you need - now you can very easily customize your user model with Devise. Happy coding.