Editing user details creates new user. Devise, Rai

2019-05-10 07:46发布

问题:

I have weird problem, previous created form instead of updating user details such as e-mail or name creates new user with given details.

My form: this code example I took from views/devise/registrations/edit

<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { "data-parsley-validate" => true, :id=>"user-edit"},remote: true, format: :json) do |f| %>   

    <div class="form-group">
        <%= f.text_field :name,:class=>"user-input form-control", :id=>"user-name" ,:placeholder=> "Lietotājvārds*",:"data-parsley-group"=>"f1" %>               
    </div>

    <div class="form-group">    
        <%= f.email_field :email ,:class=>"user-input form-control", :id=>"password",:placeholder=> "E-pasts *",:"data-parsley-group"=>"f2" %>                            
    </div>   

    <div class="form-group">                  
        <%= f.password_field :current_password, :autocomplete => "off"  ,:class=>"user-input form-control", :id=>"password",:placeholder=> "Vecā parole*                       ",:"data-parsley-group"=>"f3" %>  
    </div>

    <div class="form-group">                      
        <%= f.password_field :password , :class=>"user-input form-control", :id=>"password",:placeholder=> "Jaunā parole*                       vismaz 8 simboli ",  :"data-parsley-group"=>"f3" %>  
    </div>

    <div class="form-group">                        
       <%= f.password_field :password_confirmation , :class=>"user-input form-control", :id=>"password",:placeholder=> "Atkārtot paroli *                     vismaz 8 simboli ",  :"data-parsley-group"=>"f3" %>      
    </div>

    <button type="submit" class="blue-button btn btn-default">Apstiprināt</button>
<%end%>

Routes file:

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

Registration controller:

class RegistrationsController < Devise::RegistrationsController 

    clear_respond_to   
    respond_to :json

   def sign_up_params
    params.require(:user).permit( :email, :password, :password_confirmation,:name, :not_a_robot,:current_password,:bypass_humanizer)
  end
  def account_update_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation, :current_password, :not_a_robot, :bypass_humanizer)
  end
  private :sign_up_params
  private :account_update_params


  protected

  def update_resource(resource, params)
    resource.update_without_password(params)
  end

end

In applicaion helper:

module ApplicationHelper
     def resource_name
    :user
  end

  def resource
    @resource ||= User.new
  end

  def devise_mapping
    @devise_mapping ||= Devise.mappings[:user]

  end

end

Log file:

   Started POST "/ru/users" for 85.255.65.15 at 2015-09-28 19:32:25 +0300
    Processing by RegistrationsController#create as JS
      Parameters: {"utf8"=>"✓", "user"=>{"name"=>"ooppapa", "email"=>"test11@!!!", "current_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "bypass_humanizer"=>"true", "not_a_robot"=>"1"}, "locale"=>"ru"}
      [1m[36mBanlist Load (2.0ms)[0m  [1mSELECT `banlists`.* FROM `banlists`  WHERE (ip_adress = '85.255.65.15')[0m
      [1m[35mCountry Load (1.5ms)[0m  SELECT  `countries`.* FROM `countries`  WHERE `countries`.`id` = 1 LIMIT 1
      [1m[36mRegion Load (1.3ms)[0m  [1mSELECT `regions`.* FROM `regions`  WHERE `regions`.`country_id` = 1[0m
      [1m[35m (0.4ms)[0m  BEGIN
      [1m[36mUser Exists (44.1ms)[0m  [1mSELECT  1 AS one FROM `users`  WHERE `users`.`email` = BINARY 'test11@!!!' LIMIT 1[0m
      [1m[35mUser Load (24.3ms)[0m  SELECT  `users`.* FROM `users`  WHERE `users`.`confirmation_token` = '5c5e282bd4c139c7764506b785d54119ceee5499426b555c3650cfc7190ee947'  ORDER BY `users`.`id` ASC LIMIT 1
      [1m[36mSQL (2.1ms)[0m  [1mINSERT INTO `users` (`confirmation_sent_at`, `confirmation_token`, `created_at`, `email`, `encrypted_password`, `name`, `updated_at`) VALUES ('2015-09-28 19:32:29', '5c5e282bd4c139c7764506b785d54119ceee5499426b555c3650cfc7190ee947', '2015-09-28 19:32:28', 'test11@individualki.eu', '$2a$10$mEHajmY0H1NueGrrap7NNu0LuViDEJ.imAS4jhdj1KIyPRIyej/NC', 'ooppapa', '2015-09-28 19:32:28')[0m
      Rendered devise/mailer/confirmation_instructions.html.erb (29.2ms)

    Devise::Mailer#confirmation_instructions: processed outbound mail in 1726.8ms

    Sent mail to test11@!!!.eu (776.1ms)
    Date: Mon, 28 Sep 2015 19:32:31 +0300
    From: support@!!!!.eu
    Reply-To: support@!!!!.eu
    To: test11@!!!!.eu
    Message-ID: <56096b9f98eb5_25e4640a718550c6@!!!!!>
    Subject: Confirmation instructions
    Mime-Version: 1.0
    Content-Type: text/html;
     charset=UTF-8
    Content-Transfer-Encoding: 7bit

    <p>Welcome !!!</p>

    <p>You can confirm your account email through the link below:</p>

My routes:

rake routes
  new_user_session GET    (/:locale)/users/sign_in(.:format)                    devise/sessions#new {:locale=>/lv|ee|ru/}
                  user_session POST   (/:locale)/users/sign_in(.:format)                    devise/sessions#create {:locale=>/lv|ee|ru/}
          destroy_user_session DELETE (/:locale)/users/sign_out(.:format)                   devise/sessions#destroy {:locale=>/lv|ee|ru/}
                 user_password POST   (/:locale)/users/password(.:format)                   devise/passwords#create {:locale=>/lv|ee|ru/}
             new_user_password GET    (/:locale)/users/password/new(.:format)               devise/passwords#new {:locale=>/lv|ee|ru/}
            edit_user_password GET    (/:locale)/users/password/edit(.:format)              devise/passwords#edit {:locale=>/lv|ee|ru/}
                               PATCH  (/:locale)/users/password(.:format)                   devise/passwords#update {:locale=>/lv|ee|ru/}
                               PUT    (/:locale)/users/password(.:format)                   devise/passwords#update {:locale=>/lv|ee|ru/}
      cancel_user_registration GET    (/:locale)/users/cancel(.:format)                     registrations#cancel {:locale=>/lv|ee|ru/}
             user_registration POST   (/:locale)/users(.:format)                            registrations#create {:locale=>/lv|ee|ru/}
         new_user_registration GET    (/:locale)/users/sign_up(.:format)                    registrations#new {:locale=>/lv|ee|ru/}
        edit_user_registration GET    (/:locale)/users/edit(.:format)                       registrations#edit {:locale=>/lv|ee|ru/}
                               PATCH  (/:locale)/users(.:format)                            registrations#update {:locale=>/lv|ee|ru/}
                               PUT    (/:locale)/users(.:format)                            registrations#update {:locale=>/lv|ee|ru/}
                               DELETE (/:locale)/users(.:format)                            registrations#destroy {:locale=>/lv|ee|ru/}
             user_confirmation POST   (/:locale)/users/confirmation(.:format)               devise/confirmations#create {:locale=>/lv|ee|ru/}
         new_user_confirmation GET    (/:locale)/users/confirmation/new(.:format)           devise/confirmations#new {:locale=>/lv|ee|ru/}
                               GET    (/:locale)/users/confirmation(.:format)               devise/confirmations#show {:locale=>/lv|ee|ru/}
          update_password_user PATCH  (/:locale)/user/update_password(.:format)             users#update_password {:locale=>/lv|ee|ru/}
                     edit_user GET    (/:locale)/user/edit(.:format)                        users#edit {:locale=>/lv|ee|ru/}
                   sms_receive GET    (/:locale)/sms/receive(.:format)                      sms#receive {:locale=>/lv|ee|ru/}
                          root GET    /(:locale)(.:format)                                  girls#index {:locale=>/lv|ee|ru/}

I am confused. Is it registration_path(resource_name) that creates this error?

Any advise could be helpful.! thanks in advance.

回答1:

The issue is in the form as it is pointing to the registration_path(resource_name) path.

The example you are using is taken from How To: Allow users to edit their account without providing a password and it says:

and provide an edit and update actions, as you would do for any other resource in your application.

Which means you need to create a route to the edit method and use it as you wish.

The example above is for updating the user without the password, but what you are doing is updating the password.

For the solutions, read How To: Allow users to edit their password

An example solution - #3:

UsersController

class UsersController < ApplicationController

  before_filter :authenticate_user!

  def edit
    @user = current_user
  end

  def update_password
    @user = User.find(current_user.id)
    if @user.update(user_params)
      # Sign in the user by passing validation in case their password changed
      sign_in @user, :bypass => true
      redirect_to root_path
    else
      render "edit"
    end
  end

  private

  def user_params
    # NOTE: Using `strong_parameters` gem
    params.require(:user).permit(:password, :password_confirmation)
  end
end

If you are using several scopes, specify the one you are signing in:

sign_in :user, @user, bypass: true

The route should be the following:

resource :user, only: [:edit] do
  collection do
    patch 'update_password'
  end
end

View

<%= form_for(@user, :url => { :action => "update_password" } ) do |f| %>
  <div class="field">
    <%= f.label :password, "Password" %><br />
    <%= f.password_field :password, :autocomplete => "off"  %>
  </div>
  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation %>
  </div>
  <div class="action_container">
    <%= f.submit %>
  </div>
<% end %>

To use "confirm_password" field to force user to enter old password before updating with the new one: Change @user.update(user_params) to @user.update_with_password(user_params) in the controller along with adding :current_password to the permitted parameters, then and add the following to the view code:

<div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password %>
</div>

Remember, Devise models are like any model in your application. If you want to provide custom behavior, just implement new actions and new controllers. Don't try to bend Devise.



回答2:

I saw your question and maybe the problem is on form call.

Try insert html: { method: :put }. With simple_form I use this way:

= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f|

How you omitted the method of send the form, it's sending as post and creating a new record, I presume.