Adding extra registration fields with Devise

devise, ruby-on-rails

Solution

OK, so what I did was just override the Devise registration controller, update routes.rb as per the devise docs to reflect this, copied and pasted the Devise code for registrations#create as is, and change the getting params part to use my own strong parameters method, and that was that.

class RegistrationsController < Devise::RegistrationsController

  def create
    build_resource(registration_params)

    if resource.save
      if resource.active_for_authentication?
        set_flash_message :notice, :signed_up if is_navigational_format?
        sign_up(resource_name, resource)
        respond_with resource, :location => after_sign_up_path_for(resource)
      else
        set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
        respond_with resource, :location => after_sign_up_path_for(resource)
      end
    else
      clean_up_passwords
      respond_with resource
    end
  end  

  private

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

end

Problem

I am trying to add some extra fields to registrations#new. Since I only want extra data and do not need different functionality, I don't see why I need to override controllers etc. So what I did was modify registrations#new as follows: ``` %h2 Sign up = form_for(resource, as: resource_name, url: registration_path(resource_name)) do ||f = devise_error_messages! %div = f.label :email %br = f.email_field :email, autofocus: true %div = f.label :title_id %br = f.text_field :title_id %div = f.label :province_id %br = f.text_field :province_id %div = f.label :first_name %br = f.text_field :first_name %div = f.label :last_name %br = f.text_field :last_name %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' ``` To enable these extra fields through the sanitizer, I updated ApplicationController as follows: ``` class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception before_filter :store_requested_url! # before_filter :authenticate_user! def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email) } devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password, :password_confirmation, :title_id, :province_id, :first_name, :last_name) } devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:email, :password, :password_confirmation, :current_password) } end def after_sign_in_path_for(resource) session[:requested_url] || root_path end private def store_requested_url # store last url as long as it isn't a /users path session[:previous_url] = request.fullpath unless request.fullpath == /\/users/ end end ``` For some reason, it is not working and the extra fields go to the database as nulls. I am using Ruby 2 and Rails 4 rc1, with Devise 3.0.0.rc.

Original source