Ruby on rails 轨道&x2B;设计:使用或不使用pasword更新用户

Ruby on rails 轨道&x2B;设计:使用或不使用pasword更新用户,ruby-on-rails,ruby,devise,Ruby On Rails,Ruby,Devise,有很多相关的问题: - - - -等等 但是,当我试图用他们的答案工作时,我从来没有得到我想要的,所以我决定发布这种问答风格 情况: 我当时正在使用一个应用程序,我想要一个“管理配置文件表单”。我想要一个表单来更新用户信息,包括电子邮件和密码,还有名字、姓氏和其他非设计字段。我只想在用户试图更改密码时需要密码字段(password和password\u confirmation)。我还想用助手构建我的表单,并将用户能够更新的字段列为白名单。我还想要Desive提供的所有方便的错误信息(比如,“您

有很多相关的问题:
-
-
-
-等等

但是,当我试图用他们的答案工作时,我从来没有得到我想要的,所以我决定发布这种问答风格

情况:

我当时正在使用一个应用程序,我想要一个“管理配置文件表单”。我想要一个表单来更新用户信息,包括电子邮件和密码,还有名字、姓氏和其他非设计字段。我只想在用户试图更改密码时需要密码字段(password和password\u confirmation)。我还想用助手构建我的表单,并将用户能够更新的字段列为白名单。我还想要Desive提供的所有方便的错误信息(比如,“您的密码必须至少包含8个字符。”或者其他任何信息);DR:剥离
参数
仅为满足您的需要,我称之为
用户参数
。在处理表单的操作中,检查
user\u params[:password]
是否为空,以及是否尝试使用
@user.update不使用密码(user\u params)
更新
@user.update(user\u params)
模型。如果适用的更新调用返回
false
@user.errors
保留解释

我是如何解决这个问题的:
我在我的
config/routes
文件中定义了
资源

resource :profile  
我为我的资源制作了一个控制器,它扩展了Desive的authenticated controller
ProfilesController
,用于管理配置文件。配置文件控制器包含几个方法 包括
user_params
,主要过滤
params
到白名单:

def user_params
  accessible = [
    :first_name,
    :last_name,
    :email,
    :password,
    :password_confirmation
  ]
  params.require(:user).permit(accessible)
end
update
处理表单的业务:

def update
  # current_user holds the logged in user
  @user = current_user
  # IF they've left the password field blank, 
  # AND the devise update_without_password method returns true
  # OR IF a full update of user (including password and password_confirmation) returns true
  # THEN re-sign them in to flush their session, and redirect them back to their dashboard, and send a success message.
  # ELSE re-present the edit form they were just on (there's a handy catcher
  # in the edit view script to render the form errors, you can find them on
  # @user.errors)

  if (user_params[:password].blank? && @user.update_without_password(user_params)) || @user.update(user_params)
    sign_in(@user, bypass: true)
    redirect_to '/dashboard', notice: 'Your profile changes have been saved.'
  else
    render 'edit'
  end
end
= form_for current_user, as: :user, url: profile_path, html: { class: '' } do |f|
# [f.label, f.text_field, f.password_field, etc...]
当然还有一个视图脚本(在我的例子中是haml脚本-
app/views/profiles/edit.html.haml
),它使用
form\u for
来呈现表单:

def update
  # current_user holds the logged in user
  @user = current_user
  # IF they've left the password field blank, 
  # AND the devise update_without_password method returns true
  # OR IF a full update of user (including password and password_confirmation) returns true
  # THEN re-sign them in to flush their session, and redirect them back to their dashboard, and send a success message.
  # ELSE re-present the edit form they were just on (there's a handy catcher
  # in the edit view script to render the form errors, you can find them on
  # @user.errors)

  if (user_params[:password].blank? && @user.update_without_password(user_params)) || @user.update(user_params)
    sign_in(@user, bypass: true)
    redirect_to '/dashboard', notice: 'Your profile changes have been saved.'
  else
    render 'edit'
  end
end
= form_for current_user, as: :user, url: profile_path, html: { class: '' } do |f|
# [f.label, f.text_field, f.password_field, etc...]
我的用户模型还包括所有Desive-y优点:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :receipts
  validate :first_name, presence: true
  validate :last_name, presence: true
  validate :email, presence: true, email: true
end
class用户
如果您确实想在不使用当前\u密码的情况下更新密码,则需要使用用户
重置\u密码
方法

@user.reset_password(params[:user][:password], params[:user][:password_confirmation])
以下是在所有情况下都适用的问题的完整工作解决方案:

  if params.dig(:user, :password).blank?
    updated = @user.update_without_password(params[:user].to_unsafe_hash)
  else
    if params.dig(:user, :current_password).nil?
      @user.reset_password(params[:user][:password], params[:user][:password_confirmation])

      updated = @user.update_without_password(params[:user].to_unsafe_hash)
    else
      updated = @user.update_with_password(params[:user].to_unsafe_hash)
    end

    bypass_sign_in(@user)
  end
记录在案:这是“官方”解决方案-。