【问题标题】:Rails3 + Devise : prevent password validation when updatingRails3 + Devise:更新时防止密码验证
【发布时间】:2012-08-24 14:01:55
【问题描述】:

我正在寻找一种方法来允许用户更改他们的设置(用户模型)而不必更改他们的密码(他们仍然必须输入他们当前的密码)。开箱即用的设计似乎允许这样做,但是当您删除可验证模块并设置自定义验证时,您似乎需要解决一些问题。

我在我的用户模型中设置了以下验证:

validates :password, length: { in: 6..128 }

注册时,用户需要指定他的密码(这是我所期望的)。但是,在更新设置时,如果我将密码留空,则会向用户提出一个错误,提示密码必须至少为 6 个字符。

我怎样才能在不改变 Devise 的工作方式或实现某种自定义控制器的情况下解决这个问题?

【问题讨论】:

    标签: ruby-on-rails-3 devise


    【解决方案1】:

    也许这对某些人来说看起来很明显,但我花了一段时间才把它放在一起。经过几个小时尝试不同的解决方案和变通方法并四处寻找之后,我深入研究了 Rails 验证,并发现了一些结构,当它们组合在一起时,这真的很容易。

    我所要做的就是为创建操作设置一个验证,为更新操作设置一个验证,并在更新时允许空白。

      validates :password, length: { in: 6..128 }, on: :create
      validates :password, length: { in: 6..128 }, on: :update, allow_blank: true
    

    这样,我得到了我想要的行为,而且它只是两行短代码。

    补充说明:

    一开始我是这样尝试的:

    validates :password, length: { in: 6..128 }, on: :create
    

    这是错误的,因为它会在更新时完全跳过验证。然后,用户可以在更新设置时设置短/长(或空白?)密码。

    【讨论】:

      【解决方案2】:

      我尝试了 Amal Kumar S 解决方案,但不幸的是它并没有帮助我解决同样的问题,所以这里是在实际项目中测试的解决方案的修改版本。

      这是来自 devise/models/validatable.rb 模块的代码

      protected
      
      # Checks whether a password is needed or not. For validations only.
      # Passwords are always required if it's a new record, or if the password
      # or confirmation are being set somewhere.
      def password_required?
        !persisted? || !password.nil? || !password_confirmation.nil?
      end
      

      如果您在更新用户信息时将密码和密码确认字段留空,则验证失败,因为此条件始终为假:

      !password.nil? || !password_confirmation.nil? 
      

      Password 和 password_confirmation 字段等于空白字符串 '',它永远不等于 nil。所以你可以通过覆盖password_required来解决这个问题?用户模型中的方法并更改为零?检查空白?检查。

      protected
      
      def password_required?
       !persisted? || !password.blank? || !password_confirmation.blank?
      end
      

      认为这是解决该问题的最简单方法,并且不会破坏原始逻辑。也许是设计的错误。

      【讨论】:

      • 我能够使用它来处理我的用例,在从控制台添加用户时跳过密码要求(因为我使用的是 devise_invitable 模块)。我必须将 !persisted? 更改为 persisted? 才能做到这一点。
      【解决方案3】:

      将此代码添加到您的用户模型中。

      private
      def password_required?
        new_record? ? super : false
      end  
      

      【讨论】:

        【解决方案4】:

        Devise 有自己的方法来实现这一点,update_without_password,它更新记录属性而不询问当前密码。从不允许更改当前密码。

        注意。如果您正在使用此方法,您可能应该重写此方法以保护您不想在没有密码的情况下更新的其他属性。

        例子:

        def update_without_password(params={})
          params.delete(:email)
          super(params)
        end
        

        这一切都在设计文档中。 http://rdoc.info/gems/devise/index

        【讨论】:

          猜你喜欢
          • 2015-05-12
          • 2018-01-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多