Ruby-on-rails 设计无密码更新用户

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5113248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:30:14  来源:igfitidea点击:

Devise update user without password

ruby-on-railsdevise

提问by kriysna

I want to update users attributes without password in devise. The case is like, if password and password confirmation fields are not blank then I need devise error and if they are blank then other user attributes need to be updated. How could I do this with devise?

我想在没有密码的情况下更新用户属性。情况就像,如果密码和密码确认字段不为空,那么我需要设计错误,如果它们为空,则需要更新其他用户属性。我怎么能用设计做到这一点?

Thanks in advance!

提前致谢!

采纳答案by Dty

Is this what you're look for? From the Devise wiki

这是你要找的吗?来自设计维基

Allow users to edit their account without providing a password

允许用户在不提供密码的情况下编辑他们的帐户

It shows how to do it for rails 3 and rails 4

它显示了如何为 rails 3 和 rails 4 执行此操作

=======================

========================

John's solutionis a simpler alternative

约翰的解决方案是一个更简单的选择

回答by John

I think this is a much better solution:

我认为这是一个更好的解决方案:

if params[:user][:password].blank? && params[:user][:password_confirmation].blank?
    params[:user].delete(:password)
    params[:user].delete(:password_confirmation)
end

This prevents you from having to change the Devise controller by simply removing the password field from the form response if it is blank.

这可以防止您通过简单地从表单响应中删除密码字段(如果它是空白的)来更改设计控制器。

Just be sure to use this before@user.attributes = params[:user]or whatever you use in your updateaction to set the new parameters from the form.

请务必在之前@user.attributes = params[:user]或在update操作中使用的任何内容之前使用它来设置表单中的新参数。

回答by Duncan Robertson

I think with Devise 3.2+ you can just override update_resource in your subclassed controller. Here's an example for the question originally asked:

我认为使用 Devise 3.2+ 你可以在你的子类控制器中覆盖 update_resource 。这是最初提出的问题的示例:

class MyRegistrationsController < Devise::RegistrationsController
  protected

  def update_resource(resource, params)
    resource.update_without_password(params)
  end
end

回答by Mikhail Grishko

I solved this problem as follows: if form submitting with password, then need fill current_password field or form updated without password and current_password

我解决这个问题如下:如果表单提交密码,则需要填写 current_password 字段或没有密码和 current_password 更新表单

in model:

在模型中:

class User
  devise: bla-bla-bla

  attr_accessor :current_password
end

In controller:

在控制器中:

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

回答by graudeejs

I instead override #password_required? method inside user model.

我改为覆盖#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

So if user is new he will be required to specify password. However exist user will be required to specify password only if he fills in either password or password_confirmation attributes.

因此,如果用户是新用户,他将需要指定密码。但是,仅当用户填写 password 或 password_confirmation 属性时,才要求存在用户指定密码。

For more details see: 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#L33

My implementation is almost identical as original: https://github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L53

我的实现与原始实现几乎相同:https: //github.com/plataformatec/devise/blob/master/lib/devise/models/validatable.rb#L53

except that I check for presence (which returns false for blank strings)

除了我检查是否存在(对于空白字符串返回 false)

Here's discussion about my pull request on this matter: https://github.com/plataformatec/devise/pull/3920

这是关于我对此事的拉取请求的讨论:https: //github.com/plataformatec/devise/pull/3920

回答by rb-

I solve this problem with my interface. There are two ways it can go.

我用我的界面解决了这个问题。它有两种方式。

Disable the fields if they are empty

如果字段为空,则禁用它们

This bit of jQuery disables the fields before the form submits in the event that they are empty. It requires a certain markup pattern, check the demo on Codepen.

如果字段为空,jQuery 的这一位会在表单提交之前禁用这些字段。它需要一定的标记模式,请查看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");
      }
    });
  });
});

Give the user a checkbox to select if they want to update

给用户一个复选框以选择他们是否要更新

Another option is to remove the password fields from the form if the user hasn't indicated that they want to update their password. Here's the example on CodePen.

如果用户没有表明他们想要更新他们的密码,另一种选择是从表单中删除密码字段。这是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();
});

In either case, it requires no update to the app itself. You are just submitting the fields you want to change.

在任何一种情况下,它都不需要更新应用程序本身。您只是提交要更改的字段。

回答by Sebyddd

If you still want to support password change but make it optional, check the availability of current_passwordas such:

如果您仍然希望支持密码更改但使其成为可选,请检查以下内容的可用性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

That way if the current_password is present you can proceed and update the password, else ignore it and update without password.

这样,如果 current_password 存在,您可以继续并更新密码,否则忽略它并在没有密码的情况下更新。

回答by Changwoo Rhee

params[:user][:password] is not working in rails 6

params[:user][:password] 在 rails 6 中不起作用

You have to change params[:user][:password]to params[:password]

您必须将params[:user][:password]更改为params[:password]

Remove [:user] in all params

删除所有参数中的 [:user]

my source code is below

我的源代码在下面

before run this command

在运行此命令之前

rails generate devise:controllers users -c=registrations

rails generate devise:controllers users -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

回答by Roman

As workaround put in your User model

作为您的用户模型中的解决方法

def password_required?
  encrypted_password.blank? || encrypted_password_changed?
end

回答by Maxim Kachanov

If you want Devise to check current password only when user tries to change password(that means you canchange other attributes without providing current password):

如果您希望设计仅在用户尝试更改密码时检查当前密码(这意味着您可以在不提供当前密码的情况下更改其他属性):

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

Also in your model:

同样在您的模型中:

attr_accessor :current_password

And don't forget about

不要忘记

devise_for :users, controllers: {registrations: 'registrations'}

in routes.rb.

routes.rb 中