我想在设计中更新没有密码的用户属性。情况就像,如果密码和密码确认字段不是空白,那么我需要设计错误,如果它们是空白,则需要更新其他用户属性。我怎么能用设计做到这一点?
提前致谢!
答案 0 :(得分:84)
我认为这是一个更好的解决方案:
if params[:user][:password].blank? && params[:user][:password_confirmation].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
这可以防止您只需从表单响应中删除密码字段即可更改Devise控制器,如果它是空白的。
请确保在 @user.attributes = params[:user]
之前使用此或在update
操作中使用的任何内容从表单中设置新参数。
答案 1 :(得分:61)
这是你要找的吗?来自Devise wiki
Allow users to edit their account without providing a password
它显示了如何为rails 3和rails 4
执行此操作=======================
John's solution是一个更简单的替代方案
答案 2 :(得分:18)
我认为使用Devise 3.2+,您可以覆盖子类控制器中的update_resource。以下是最初提出的问题的示例:
class MyRegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
resource.update_without_password(params)
end
end
答案 3 :(得分:7)
我解决了这个问题如下:如果表单提交密码,则需要填写current_password字段或表格更新,不带密码和current_password
模特中的:
class User
devise: bla-bla-bla
attr_accessor :current_password
end
在控制器中:
class Users::RegistrationsController < Devise::RegistrationsController
layout 'application'
def update
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
# custom logic
if params[:user][:password].present?
result = resource.update_with_password(params[resource_name])
else
result = resource.update_without_password(params[resource_name])
end
# standart devise behaviour
if result
if is_navigational_format?
if resource.respond_to?(:pending_reconfirmation?) && resource.pending_reconfirmation?
flash_key = :update_needs_confirmation
end
set_flash_message :notice, flash_key || :updated
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
end
答案 4 :(得分:3)
我用我的界面解决了这个问题。有两种方法可以实现。
这些jQuery在表单提交之前禁用字段,如果它们为空。它需要一定的标记模式,请检查demo on Codepen。
$(".password-fields").each(function() {
var $fields, $form;
$form = $(this).parents("form");
$fields = $(this).find("input");
$form.on("submit", function() {
$fields.each(function() {
if ($(this).val() === "") {
$(this).attr("disabled", "disabled");
}
});
});
});
另一个选择是如果用户没有表明他们想要更新密码,则从表单中删除密码字段。这是示例on CodePen。
$(".password-fields").each(function () {
var $fields, $button, html;
$fields = $(this);
$button = $fields.prev(".update-password").find("input");
html = $fields.html();
$button
.on("change", function () {
if ( $(this).is(":checked") ) {
$fields.html(html);
}
else {
$fields.html("");
}
})
.prop("checked", "checked")
.click();
});
在任何一种情况下,它都不需要更新应用程序本身。您只是提交要更改的字段。
答案 5 :(得分:3)
我改为覆盖#password_required?用户模型中的方法。
class User < ActiveRecord::Base
devise :database_authenticatable, :validatable #, ...
def password_required?
if respond_to?(:reset_password_token)
return true if reset_password_token.present?
end
return true if new_record?
password.present? || password_confirmation.present?
end
end
因此,如果用户是新用户,则需要指定密码。 但是,只有当用户填写password或password_confirmation属性时,才需要指定用户。
有关详细信息,请参阅: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L33
我的实现几乎与原始版本相同: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L53
除了我检查是否存在(对空字符串返回false)
以下是关于此问题的拉取请求的讨论:https://github.com/plataformatec/devise/pull/3920
答案 6 :(得分:3)
如果您仍想支持密码更改但要将其设为可选,请检查current_password
的可用性:
class MyRegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
if params[:current_password].blank?
resource.update_without_password(params.except(:current_password))
else
resource.update_with_password(params)
end
end
end
这样,如果current_password存在,您可以继续并更新密码,否则忽略它并在没有密码的情况下更新。
答案 7 :(得分:2)
params [:user] [:password]在rails 6中不起作用
您必须将 params [:user] [:password] 更改为 params [:password]
删除所有参数中的[:user]
我的源代码在下面
在运行此命令之前
rails产生devise:controllers用户-c = registrations
class Users::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]
protected
def update_resource(resource, params)
puts "params ===> #{params}"
if params[:password].blank? && params[:password_confirmation].blank?
params.delete(:password)
params.delete(:password_confirmation)
params.delete(:current_password)
resource.update_without_password(params)
else
super
end
end
end
答案 8 :(得分:1)
如果您希望Devise仅在用户尝试更改密码时检查当前密码 (表示您可以更改其他属性而不提供当前密码 >):
class RegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
if params[:password].blank? && params[:password_confirmation].blank?
resource.update_without_password(params)
else
super
end
end
end
同样在你的模特中:
attr_accessor :current_password
别忘了
devise_for :users, controllers: {registrations: 'registrations'}
routes.rb 中的。
答案 9 :(得分:1)
任何在2020年访问的人,这是我发现的最简单的解决方案:
在registrations_controller.rb
中:
class RegistrationsController < Devise::RegistrationsController
protected
def update_resource(resource, params)
# Require current password if user is trying to change password.
return super if params["password"]&.present?
# Allows user to update registration information without password.
resource.update_without_password(params.except("current_password"))
end
end
在routes.rb中:
devise_for :users, controllers: {
registrations: 'users/registrations'
}
可归功于:西口正俊
https://www.mnishiguchi.com/2017/11/24/rails-devise-edit-account-without-password/
答案 10 :(得分:1)
对于未来的Google员工,我花了3个小时在这里,这对我有用。
在我的用户模型中,仅当密码和password_confirmation存在时,我删除:validatable并添加了validates方法:
class User < ApplicationRecord
devise :database_authenticatable, :registranable, recoverable, :rememberable
validates :password, length: { in: 6..128 }, if: lambda {self.password.present?}
validates_confirmation_of :password, if: lambda {self.password.present?}
end
然后在users_controller的更新方法中,如果密码和password_confirmation参数为空,则将它们删除
class UsersController > ApplicationController
def update
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to @user, notice: 'User was successfully updated' }
else
format.html { render :edit }
end
end
end
end
Devise复杂的做事方式使事情变得简单,简单,轻松且无所不包。
不客气。
答案 11 :(得分: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
答案 12 :(得分:0)
要更新用户的属性,您将需要使用:current_password,以检查“您的用户使用了正确的current_password还是有人想破坏您的用户”
所以形式:
= f.input :current_password,
hint: "we need your current password to confirm your changes",
required: true,
input_html: { autocomplete: "current-password" }
在控制器中:
if your_user.valid_password?(params[:user][:current_password])
your_user.update_attributes(user_params.except(:current_password, :password, :password_confirmation))
end
第一行检查“您的用户是否发送了正确的密码”,然后我们就可以更新属性而不会产生垃圾
答案 13 :(得分:0)
更好和更简短的方法:将检查参数添加到user_params块中。 例如:
def user_params
up = params.require(:user).permit(
%i[first_name last_name role_id email encrypted_password
reset_password_token reset_password_sent_at remember_created_at
password password_confirmation]
)
if up[:password].blank? && up[:password_confirmation].blank?
up.delete(:password)
up.delete(:password_confirmation)
end
up
end
答案 14 :(得分:0)
在对上述可能性进行了大量探索之后,我终于找到了一个解决方案,它允许您在没有密码的情况下更新某些属性,其中一些包含:
我为user / edit.html.erb制作了一个视图,其中包含以下表单。
<%= form_for(@user) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.submit "Save changes"%>
<% end %>
我在routes.rb中设置路线
resources :users, only: [:show, :index, :edit, :update]
我在users_controller.rb中编辑和更新了方法
def edit
@user = current_user
end
def update
@user = current_user
if @user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to root_url
else
render 'edit'
end
end
def user_params
params.require(:user).permit(:name, :avatar, :whatsup)
end
我使用此编辑视图进行不需要密码的更改。它完全跳过设计注册控制器,因为我用
链接到它edit_user_path(current_user)
我还设置了参数,以便在此处无法更改电子邮件和密码。要更新密码和电子邮件,我链接到库存生成设计视图:
edit_user_registration_path(current_user)
我承认这是一个巨大的工作,但没有一个更简单的解决方案解决了上述所有问题。
答案 15 :(得分:0)
我发现以上代码的这种轻微变化更容易理解:
def update
@user = User.find(params[:id])
method = if user_params[:password].blank?
:update_without_password
else
:update_with_password
if @user.send(method, user_params)
redirect_to @user, notice: 'User settings were saved.'
else
render :edit
end
end
答案 16 :(得分:0)
将解决方法放入用户模型
def password_required?
encrypted_password.blank? || encrypted_password_changed?
end
答案 17 :(得分:0)
我有完全相同的问题,这是我提出的解决方案并相信我的工作原理。
我做的是创建第二个user_params
方法,并命名为user_params_no_pass
无论如何看看:这里发生的是管理员将在需要更新密码时提供密码,否则将密码留空。如果密码为空,则使用user_params_no_pass
,否则使用user_params
。我希望有帮助
def update
if @user.valid_password?(params[:user][:password])
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to @user, notice: 'User profile was successfully updated.' }
format.json { render :show, status: :ok, location: @user }
else
format.html { render :new }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
else
respond_to do |format|
if @user.update(user_params_no_pass)
format.html { redirect_to @user, notice: 'User profile was successfully updated without password.' }
format.json { render :show, status: :ok, location: @user }
else
format.html { render :edit }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
end
def destroy
@user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:user_name, :first_name, :middle_name, :last_name, :dob, :gender, :race, :hispanic, :leader, :mentor, :student, :email, :organization_id, :password, :opus,
:release_date, :days_to_release, :current_level, :is_active)
end
def user_params_no_pass
params.require(:user).permit(:user_name, :first_name, :middle_name, :last_name, :dob, :gender, :race, :hispanic, :leader, :mentor, :student, :email, :organization_id, :opus,
:release_date, :days_to_release, :current_level, :is_active)
end
答案 18 :(得分:0)
它有更多的业务逻辑,所以我不会在控制器中放入太多代码。我建议在模型中覆盖Devise::Models::Validatable#password_required?
:
def password_required?
new_record? || password.present? || password_confirmation.present?
end