【问题标题】:Updating profiles and passwords更新配置文件和密码
【发布时间】:2013-09-26 08:25:23
【问题描述】:

我不确定如何最好地解决此问题 - 添加新记录时我需要验证用户的密码,并且我还需要能够在更新密码时进行验证。但是我怎样才能让用户只更新他们的部分个人资料,并可能将密码留空。

注意在您建议 allow_blank 之前,我知道此选项,但这不合适,因为当用户因丢失/忘记密码而需要更改密码时,我不想允许用户密码为空。

【问题讨论】:

    标签: ruby-on-rails validation ruby-on-rails-4


    【解决方案1】:
    validates :password, presence: true, if: lambda { |user| user.password_changed? }
    

    by ActiveModel::Dirty(默认适用于所有模型)

    【讨论】:

      【解决方案2】:

      您可以将 if 语句传递给验证:

      `validates_presence_of :password, :if => :should_validate_password?

      你应该可以在这里传递一个条件来判断用户是否正在更新他们的密码:

      型号

      def should_validate_password?
        updating_password || new_record?
      end
      

      控制器

      @user.updating_password = true
      @user.save
      

      更多详情请看这里:http://railscasts.com/episodes/41-conditional-validations

      更新:

      在您的情况下,我将在控制器中创建一个 if 语句,以检测参数中是否传递了任何新密码。如果是这样,我会设置@user.updating_password = true,这将触发模型中的验证。如果不是,那么@user.updating_password 将为 nil,并且不会触发验证。

      【讨论】:

      • 看起来很有用——因为这个 Railscast 已经很老了,这是在创建和更新之前吗?但是,我应该能够利用条件的概念。
      • 是的,您可以使用基于操作的条件,但我认为您可能需要比仅针对特定操作更多的粒度。
      • 但仅此而已 - 我不能使用“基于动作的条件”,因为没有适用于所有场景的组合
      • 我需要一些东西,在使用编辑页面时允许在更新时出现空白,但在从重置密码页面更新密码时不允许出现空白 - 所以应该能够按照您的建议进行操作
      • 是的,这正是我要说的。使用这种更精细的 if 语句方法来准确指定您的场景所需的内容。
      【解决方案3】:

      完全自定义方式

      通常,#password=#password_confirmation= 只是虚拟设置器,真正的属性是#hashed_password 什么的。所以,你可以这样做:

      class User
        attr_accessor :password, :password_confirmation
      
        validate :validates_password
        validates_presence_of :hashed_password
      
        private
      
        def validates_password
          if password or password_confirmation
            if password != password_confirmation
              errors.add( :password, 'your message' )
            end
            # your others validations
      
            self.hashed_password = hash_password
          end
        end
      
        def hash_password
          # your hashing code
        end
      end
      

      当创建用户提供密码时,虚拟属性passwordpassword_confirmation 被设置,所以if 条件为真并强制执行验证。

      当密码已经设置并且用户没有更改它(一个没有提供密码的编辑表单),验证将不会被强制执行,因为if password and password_confirmation

      当密码已经设置并且用户更改密码时,passwordpassword_confirmation 被设置,因此触发验证。

      当您想重置密码时,只需在您的操作中将hashed_password 设置为 nil。由于validates_presence_of :hashed_password,该模型现在无效,用户必须提供一个新模型。

      使用#has_secure_password

      使用#has_secure_password,rails 将处理大部分问题,尤其是:

      • 它创建虚拟属性
      • 仅当提供密码属性时才会触发确认匹配验证
      • 它会散列密码

      因此,您只需添加自己的验证,仅在存在 passwordpassword_confirmation 时执行。

      class User
        has_secure_password
        validate :validates_password
      
        private
      
        def validates_password
          if password or password_confirmation
            unless <your_test>
              errors.add( :password, '<your error message>' )
            end
          end
        end
      end
      

      如前所述,只有在提供密码和密码确认时才会触发,只有当用户将它们作为表单数据提交时才会触发(因为真实属性是password_digest)。

      【讨论】:

      • 谢谢 - 但这如何让用户在编辑页面上输入空格并要求非空格作为重置密码?这两个都是更新操作。
      • if password or password_confirmation 将避免验证字段,如果没有提供。 validates_presence_of :ashed_password 在从未提供过密码的情况下如果不提供密码将触发错误。对于 reset_password,只需在操作中将 #hashed_password 设置为 nil,然后再尝试保存记录。
      • 抱歉,我在您的代码中看不到编辑密码和重置密码的处理方式有何不同??? if password or password_confirmation 在这两种情况下都会被忽略 - 我需要在 Rails4 中使用 attr_accessor 吗?
      • 抱歉刚刚看到你的修改 - 一会儿
      • 好的 - 我明白了 - 有趣的方法 - 但还有一件事。为什么我需要 hash_password 操作?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多