Saving custom fields in devise User model in rails

2019-03-15 13:40发布

问题:

I made a devise User model and added additional fields to it. When I create and account everything works fine, only with email, pw and pw conf.

I then want to allow the user to go to edit page and fill in the optional additional fields. But, when they submit, everything is saved as nil.

 class RegistrationsController < Devise::RegistrationsController

   before_action :configure_permitted_parameters, if: :devise_controller?

   def configure_permitted_parameters
     devise_parameter_sanitizer.for(:sign_in){ |u| u.permit(:email, :password) }
     devise_parameter_sanitizer.for(:sign_up){ |u| u.permit(:name, :username, :about,  :email, :password, :password_confirmation)}
     devise_parameter_sanitizer.for(:account_update){ |u| u.permit(:name, :username, :about, :email, :password, :password_confirmation) }
   end

   def update
     self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
     if resource.update_with_password(user_params)
       if is_navigational_format?
         flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ? :update_needs_confirmation : :updated
         set_flash_message :notice, flash_key
       end
       sign_in resource_name, resource, :bypass => true
       respond_with resource, :location => after_update_path_for(resource)
     else
       clean_up_passwords resource
       respond_with resource
     end
   end

   def user_params 
     params.require(:user).permit(:email, :password, :current_password, :password_confirmation, :name, :username, :about) 
   end
 end

I get this output in the console,

 ActiveRecord::SchemaMigration Load (0.1ms)  SELECT "schema_migrations".* FROM "schema_migrations"
 Processing by Devise::RegistrationsController#update as HTML
 Parameters: {"utf8"=>"✓", "authenticity_token"=>"EG8FtCTBohuG2uwUvIqmY7KTsmYY1nMAXqTfc0Li+eQ=", 
 "user"=>{"email"=>"a@a.com", "name"=>"Aaron", "username"=>"", "about"=>"", 
 "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}

User Load (2.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
Unpermitted parameters: name, username, about

But nothing is saved in the database when I check in the console (with User.last). I am stuck, and have looked and have no idea what is wrong...

回答1:

In Rails4 we have strong parameters so please

Add following line to your application_controller.rb

before_filter :configure_devise_params, if: :devise_controller?
  def configure_devise_params
    devise_parameter_sanitizer.for(:sign_up) do |u|
      u.permit(:first_name, :last_name, :gender, :email, :password, :password_confirmation)
    end
  end


回答2:

After working on something similar to this, I settled on using Application Controller, then afterward found that the Devise Documentation is fairly straightforward for this in their strong parameters section and gives an alternative to using Application Controller. https://github.com/plataformatec/devise#strong-parameters

Below is the approach with Application Controller which worked for me.

    class ApplicationController < ActionController::Base

      before_filter :configure_permitted_parameters, if: :devise_controller?

      private

      def configure_permitted_parameters
         devise_parameter_sanitizer.for(:sign_up){ |u| u.permit(:name, :username, :about,  :email, :password, :password_confirmation)}        
         devise_parameter_sanitizer.for(:account_update){ |u| u.permit(:name, :username, :about, :email, :password, :password_confirmation) }          
      end

    end

This should work the same and it directly overwrites methods in Devise::RegistrationController.

    class Users::RegistrationsController < Devise::RegistrationsController

      private

      def configure_sign_up_params
        devise_parameter_sanitizer.for(:sign_up){ |u| u.permit(:name, :username, :about,  :email, :password, :password_confirmation)}
      end

      def configure_account_update_params
        devise_parameter_sanitizer.for(:account_update){ |u| u.permit(:name, :username, :about, :email, :password, :password_confirmation) }
      end

    end


回答3:

First produce new field. for reference http://guides.rubyonrails.org/migrations.html

Do you have add your new fields in user controller parameter?

   def user_params
      params.require(:user).permit(:email, :password, :password_confirmation)
    end

    def sign_up_params
      params.require(:user).permit(:email, :password, :password_confirmation)
    end

In the application controller

before_filter :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:email, :password, :password_confirmation)}

    devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:email, :password, :password_confirmation)}
  end

In your registration form that override devise add this

class Users::RegistrationsController < Devise::RegistrationsController
     skip_before_filter :verify_authenticity_token, :only => [:ipn_notification]
  def sign_up_params
      params.require(:user).permit(:email, :password, :password_confirmation)
  end

After that add your new fields in all views _form,show,edit,index.



回答4:

In Rails 4.2, this is how I did. I have User Model on which devise is applied.
Use this command "rails generate devise:controllers users" to generate custom controllers.
I have added "username" name attribute to my User Model

In my controller

class Users::RegistrationsController < Devise::RegistrationsController
 before_filter :configure_sign_up_params, only: [:create]
 before_filter :configure_account_update_params, only: [:update]
 #rest of code as generated

   protected

    # If you have extra params to permit, append them to the sanitizer.
    def configure_sign_up_params
      devise_parameter_sanitizer.for(:sign_up) << :username
    end

   # If you have extra params to permit, append them to the sanitizer.
   def configure_account_update_params
     devise_parameter_sanitizer.for(:account_update) << :username
   end

In Routes

devise_for :users, controllers: {registrations: "users/registrations"}