Rails 4.0 with Devise. Nested attributes Unpermited parameters

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| %>
  <ul>

    <%= devise_error_messages! %>

    <li class="fullname">
      <%= f.fields_for :profile do |profile_fields| %>
        <%= profile_fields.label :fullname %>
        <%= profile_fields.text_field :fullname %>
      <% end %>
    </li>
    <li class="email">
      <%= f.label :email %>
      <%= f.email_field :email, :autofocus => true %>
    </li>
    <li class="password">
      <%= f.label :password %>
      <%= f.password_field :password %>
    </li>
    <li class="password">
      <%= f.label :password_confirmation %>
      <%= f.password_field :password_confirmation %>
    </li>
    <li>
      <%= f.submit %>
    </li>
    <li>
      <p><%= render "devise/shared/links" %></p>
    </li>
  </ul>
<% end %>

Leave a Comment