I am working on a web-app using Devise and Rails 4. I have a User model which I have extended with 2 extra form fields such that when a user signs up he can
config/routes.rb
Create your own registration controller like so ... (see Devise documentation for the details of overriding controllers here ...) ... which is more elegant way as opposed to doing it via the ApplicationController
devise_for :users, controllers: {registrations: 'users/registrations'}
app/controllers/users/registrations_controller.rb
Override the new method to create a Profile associated with the User model as below ... run the configure_permitted_parameters method before to sanitize the parameters (note how to add nested parameters)
class Users::RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
# GET /users/sign_up
def new
# Override Devise default behaviour and create a profile as well
build_resource({})
resource.build_profile
respond_with self.resource
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
u.permit(:email, :password, :password_confirmation, :profile_attributes => :fullname)
}
end
end
db/migrate/xxxxxxxxxxxxxx_create_profiles.rb
This is the migration that generates the Profile model (note the reference to User) ... this example profile only keeps fullname as an extension of the User but feel free to add as you wish!
class CreateProfiles < ActiveRecord::Migration
def change
create_table :profiles do |t|
t.references :user
t.string :fullname
t.timestamps
end
end
end
app/models/user.rb
class User < ActiveRecord::Base
# Associations
has_one :profile, dependent: :destroy, autosave: true
# Allow saving of attributes on associated records through the parent,
# :autosave option is automatically enabled on every association
accepts_nested_attributes_for :profile
# Devise
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
app/models/profile.rb
class Profile < ActiveRecord::Base
# Associations
belongs_to :user
# Validations
validates :fullname, presence: true
end
app/views/devise/registrations/new.html
<% resource.build_profile if resource.profile.nil? %>
<%= form_for(resource, :as => resource_name,
:url => registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
-
<%= f.fields_for :profile do |profile_fields| %>
<%= profile_fields.label :fullname %>
<%= profile_fields.text_field :fullname %>
<% end %>
-
<%= f.label :email %>
<%= f.email_field :email, :autofocus => true %>
-
<%= f.label :password %>
<%= f.password_field :password %>
-
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
-
<%= f.submit %>
-
<%= render "devise/shared/links" %>
<% end %>