【问题标题】:Rails: Validate only on create, or on update when field is not blankRails:仅在创建时验证,或者当字段不为空时在更新时验证
【发布时间】:2014-06-18 07:54:32
【问题描述】:

当字段不为空时,如何限制 Rails 验证只检查创建或?我正在为我正在开发的应用程序创建一个用户设置页面,问题是,当使用表单提供的参数进行更新时,设置只会在密码和密码确认都存在时保存。无论如何,我希望这些密码字段在创建时验证,但仅在提供时更新。

【问题讨论】:

    标签: ruby-on-rails ruby rails-activerecord


    【解决方案1】:

    如果您想允许空白值,请使用:allow_blank with validates。

    class Topic < ActiveRecord::Base
      validates :title, length: { is: 5 }, allow_blank: true
    end
    

    如果您只想在创建时进行验证,请将on 与验证一起使用。

    class Topic < ActiveRecord::Base
      validates :email, uniqueness: true, on: :create
    end
    

    覆盖你的情况:

    class Topic
      validates :email, presence: true, if: :should_validate?
    
      def should_validate?
        new_record? || email.present?
      end
    end
    

    【讨论】:

    • if: :should_validate? 非常有用,而且高度可定制。谢谢。
    【解决方案2】:

    事实证明这比我想象的要简单一些。我将表单输入名称从passwordpassword_confirmation 更改为new_passwordnew_password_confirmation。我使用以下行在我的模型中为这些值添加了临时访问器:

    attr_accessor :new_password, :new_password_confirmation
    

    我实现了一个password_changed? 方法,定义如下:

    def password_changed?
        !new_password.blank?
    end
    

    最后,我将验证更改为:

    validates :new_password, presence: true, confirmation: true, length: { in: 6..20 }, on: :create
    validates :new_password, presence: true, confirmation: true, length: { in: 6..20 }, on: :update, if: :password_changed?
    validates :new_password_confirmation, presence: true, on: :create
    validates :new_password_confirmation, presence: true, on: :update, if: :password_changed?
    

    我很肯定有更好的方法来做到这一点(这不是很干),但现在,它有效。改进的答案仍然非常感谢。

    【讨论】:

      【解决方案3】:

      无需更改字段名称,将代码中的:password_changed? 替换为:password_digest_changed? 即可。

      validates :password, presence: true, confirmation: true, length: { in: 6..20 }, on: :create
      validates :password, presence: true, confirmation: true, length: { in: 6..20 }, on: :update, if: :password_digest_changed?
      validates :password_confirmation, presence: true, on: :create
      validates :password_confirmation, presence: true, on: :update, if: :password_digest_changed?
      

      【讨论】:

        【解决方案4】:

        请尝试

        validates :<attributes>, if: Proc.new{|obj| obj.new_record? || !obj.<attribute>.blank? }
        

        或添加自定义方法名称而不是属性名称。

        【讨论】:

        • 我会使用 lambda 而不是 proc:-&gt;(obj) { obj.new_record? || ... }
        • 奇怪的是,添加这个验证似乎会导致我的长度验证失败,抛出错误:“密码太长(最多 20 个字符)。”我的验证如下所示:validates :password, confirmation: true, presence: true, length: { in: 6..20 }, if: -&gt;(obj) { obj.new_record? || !obj.password.blank? }
        • 是的@Jamie,您可以使用任何带有 if 条件的选项。
        【解决方案5】:

        这行得通

        validates :password, presence: true, length: { in: 6..20 }, if: :password_digest_changed?
        

        Bcrypt gem 要求 password 和 password_confirmation 相同,所以你真的只需要担心其中一个。在两者上,密码摘要的更新和创建都会改变。这意味着验证是在创建时调用的,并且只有在用户更新密码时才会在更新时调用。您应该在前端进行 js 验证,但是这一行代码将在更新和创建时保护数据库。我自己对此进行了测试。您可能可以对此使用自定义验证,但我自己没有尝试过。游戏迟到了,希望这对某人有所帮助。

        【讨论】:

          猜你喜欢
          • 2023-04-02
          • 1970-01-01
          • 1970-01-01
          • 2020-05-26
          • 1970-01-01
          • 2013-10-16
          • 2018-10-06
          • 2010-11-26
          • 1970-01-01
          相关资源
          最近更新 更多