有很多相关的问题:
- 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个字符。"或者它们是什么)。
答案 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