How to create a profile for devise user?

2019-09-15 16:05发布

问题:

I'm new to rails and trying to create a profile for devise users when they signup, using nested form in devise signup. I've gone through Creating Profile for Devise users, Profile model for Devise users? and few other articles to achieve the same but after a day in vain, I'm still trying to make it work. Here is my code.

Model - user.rb

class User < ActiveRecord::Base
  has_one :user_profile
  accepts_nested_attributes_for :user_profile

  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

Model - user_profile.rb

class UserProfile < ActiveRecord::Base
  belongs_to :user
end

Controller - controllers/users/registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController
  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) {|u| 
      u.permit(:email, :password, :password_confirmation, :remember_me, 
      user_profile_attributes: [:first_name, :last_name])}
    end
  end
end

View - views/devise/registrations/new.html.erb

 <h2>Sign up</h2>
 <% resource.build_user_profile %>
 <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
   <%= devise_error_messages! %>

   <div class="field">
     <%= f.label :email %><br />
     <%= f.email_field :email, autofocus: true %>
   </div>

   <div class="field">
     <%= f.label :password %>
     <% if @minimum_password_length %>
       <em>(<%= @minimum_password_length %> characters minimum)</em>
     <% end %><br />
     <%= f.password_field :password, autocomplete: "off" %>
   </div>

   <div class="field">
     <%= f.label :password_confirmation %><br />
     <%= f.password_field :password_confirmation, autocomplete: "off" %>
   </div>

   <%= f.fields_for :user_profile do |profile_form| %>
     <%= profile_form.label :first_name %><br/>
     <%= profile_form.text_field :first_name %><br/>

     <%= profile_form.label :last_name %><br/>
     <p><%= profile_form.text_field :last_name %><br/>
   <% end %>

   <div class="actions">
     <%= f.submit "Sign up" %>
   </div>
 <% end %>

 <%= render "devise/shared/links" %>

Server Log

Processing by Devise::RegistrationsController#create as HTML
  Parameters: {"utf8"=>"√", "authenticity_token"=>"rLuFXwISxiJpWPjpmKzjnjhKr41F5
56sWbtT+8gslAMsFDWRbl7MSitSXUESjLdZccCBGBGvVv+JbhW7G5py5g==", "user"=>{"email"=>
"zebandz@gmail.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTER
ED]", "user_profile_attributes"=>{"first_name"=>"Zeban", "last_name"=>"Dezend"}}
, "commit"=>"Sign up"}
Unpermitted parameter: user_profile_attributes

I think, I'm missing the code to fetch the values from params and create a new record. Can someone suggest me the fix ?

回答1:

please follow the below steps.

devise> reg > new

    <div class="row">
          <div class="col-md-5 col-md-offset-4">

          <h2>Sign up</h2>

          <% resource.build_user_profile if resource.user_profile.nil? %>
          <%= form_for(resource, as: resource_name, url:     registration_path(resource_name)) do |f| %>
          <%= devise_error_messages! %>

           <div class="row">
           <%= f.fields_for :user_profile do |profile_form| %>
           <div  class="col-md-6">
           <div class="form-group">
             <%= profile_form.label :first_name %>
             <%= profile_form.text_field :first_name, class: "form-control" %>
           </div>
           </div>
           <div  class="col-md-6">
           <div class="form-group">
             <%= profile_form.label :last_name %>
             <%= profile_form.text_field :last_name, class: "form-control" %>
          </div>
          </div>
          <% end %>
          </div>

          <div class="form-group">
          <%= f.label :email %><br />
          <%= f.email_field :email, autofocus: true, class: "form-control" %>
</div>

          <%= f.fields_for :user_profile do |profile_form| %>
          <div class="form-group">
           <%= profile_form.label :business_name %>
           <%= profile_form.text_field :business_name, class: "form-control" %>
          </div>
          <div class="form-group">
           <%= profile_form.label :business_category %>
           <%= profile_form.collection_select :business_category_id, BusinessCategory.all, :id, :name, {prompt: "Select Category"}, {class: "form-control"} %>
          </div>
          <div class="form-group">
            <%= profile_form.label :website %>
            <%= profile_form.url_field :website, class: "form-control" %>
          </div>
         <div class="form-group">
           <%= profile_form.label :address %>
           <%= profile_form.text_area :address, class: "form-control" %>
         </div>
         <div class="form-group">
            <%= profile_form.label :personal_number %>
            <%= profile_form.text_field :phone_number, class: "form-control" %>
         </div>


    <div class="form-group">
         <%= profile_form.label :office_number %>
         <%= profile_form.text_field :office_number, class: "form-control" %>

   </div>
<% end %> 

<div class="form-group">
  <%= f.label :password %>
  <% if @minimum_password_length %>
  <em>(<%= @minimum_password_length %> characters minimum)</em>
  <% end %><br />
  <%= f.password_field :password, autocomplete: "off", class: "form-control" %>
</div>

<div class="form-group">
  <%= f.label :password_confirmation %><br />
  <%= f.password_field :password_confirmation, autocomplete: "off", class: "form-control" %>
</div>

<div class="actions">
  <%= f.submit "Sign up", class: "btn btn-primary" %>
</div>
<% end %>

<%= render "devise/shared/links" %>
</div>
</div>



user reg controller

def new
    # Override Devise default behaviour and create a profile as well
    build_resource({})
    resource.build_user_profile
    respond_with self.resource
  end

protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up) { |u|
      u.permit(:email, :password, :password_confirmation, :user_profile_attributes => [:first_name, :last_name, :business_name, :business_category_id, :website, :address, :phone_number, :office_number])
    }
  end


回答2:

Have you tried following these steps from their github page? They set the permitted parameters in the ApplicationController. Also the structure is a little different. The parameters go into keys. https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

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

  protected

  def configure_permitted_parameters
    added_attrs = [:username, :email, :password, :password_confirmation, :remember_me]
    devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
    devise_parameter_sanitizer.permit :account_update, keys: added_attrs
  end
end