Rails + Devise:使用或不使用pasword更新用户

时间:2015-05-22 16:52:56

标签: ruby-on-rails ruby devise

有很多相关的问题:
  - Devise: Update Account without password confirmation
  - rails: devise update user without password
  - Devise 3 (rails 4) can't update user without password
  - 等......

但是当我尝试使用他们的答案时,我从未得到我想要的东西,所以我决定发布这个Q& A风格。

情况:
我正在使用Rails处理devise应用,我想要一个"管理个人资料表单。"我想要一个表单来更新用户信息,包括电子邮件和密码,还有first_name,last_name和其他非设计字段。如果用户试图更改密码,我只想要密码字段(password和password_confirmation)。我还希望使用form_for帮助程序构建我的表单,并将用户能够更新的字段列入白名单。而且我还想要设计所有方便的错误消息(例如,"您的密码必须至少为8个字符。"或者它们是什么)。

2 个答案:

答案 0 :(得分:2)

TL; DR :剥离params只是你想要的,我称之为user_params。在处理表单检查的操作中,如果user_params[:password]为空,并且是否尝试使用@user更新@user.update_without_password(user_params)模型,如果它没有尝试使用{{更新1}}。如果适用的更新调用返回@user.update(user_params) false,则会解释。

以下是我如何解决这个问题:
我在@user.errors文件中定义了resource

config/routes

我为我的资源创建了一个控制器,它扩展了设计用于管理配置文件的经过身份验证的控制器resource :profile 。 Profiles控制器包含几种方法 包括主要将ProfilesController < AuthenticatedController过滤到白名单的user_params

params

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

update

当然还有一个视图脚本(在我的案例中是一个haml - 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 ),它使用app/views/profiles/edit.html.haml来呈现表单:

form_for

我的用户模型还包含所有设计优点:

= form_for current_user, as: :user, url: profile_path, html: { class: '' } do |f|
# [f.label, f.text_field, f.password_field, etc...]

答案 1 :(得分:0)

如果您真的想在没有 current_password 的情况下更新密码,那么您需要使用用户 reset_password 方法

@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