【问题标题】:How can I implement dynamic validation in activerecord如何在 activerecord 中实现动态验证
【发布时间】:2015-12-15 22:20:29
【问题描述】:

根据参数或操作调整模型验证的最佳方法是什么?假设我正在将潜在客户输入系统,因此所需的只是基本联系信息。但稍后我可能会为该用户签订新合同,此时我需要更详细的信息。因此,我在输入潜在客户时可能需要电话号码,但一旦他们签订合同,我可能需要他们的出生日期和备用电话号码。

我考虑过使用状态机,但用户实际上可以同时签订两个合同,因此状态在这种情况下实际上并不适用。

我也考虑过将额外信息与合同一起存储,但由于用户可以拥有多个合同,因此它需要与用户一起使用,因此它不是多余的。

所以基本上在保存合同时,如果该用户没有额外的字段,它会告诉我附加的用户无效。

【问题讨论】:

    标签: ruby-on-rails validation activerecord


    【解决方案1】:

    查看conditional validations:

    class Person
      validates_presence_of :given_name, family_name
    
      validates_presence_of :phone_number, :email_address, :if => :registered
    
      with_options :if => :registered do |person|
        # validations in this block are scoped to a registered user
        person.validates_presence_of :dob
      end
    
    end
    

    :if 选项可以采用:

    • 一个符号,对应于评估为真或假的类上的方法
    • 一个 proc 或 lambda,它返回一个计算结果为 true 或 false 的值
    • 一个包含 ruby​​ 代码的字符串(天知道你为什么要这样做)

    您还可以访问:unless 选项,其工作方式类似。

    您还可以封装逻辑以确定用户的当前状态,并使用它来确定您可以采取哪些验证步骤:

    class Person
    
      validates_presence_of :email_address, :if => ->(p) { p.state == :pending_confirmation }
    
      # I actually prefer validations in this format
      validate do # stricter validations when user is confirming registration
        if confirming_membership && (given_name.blank? || family_name.blank?
          errors.add(:base, 'A full name is required')
        end
      end
    
      def state
        # your logic could be anything, this is just an example
        if self.confirmed_email
          :registered
        elsif confirming_membership
          :pending_confirmation
        else
          :new_user
        end
      end
    
      def confirming_membership
        # some logic
      end
    end
    

    【讨论】:

    • 我已经看过这个,但我正在尝试如何弄清楚如何在用户状态更改之前进行检查。所以他们即将注册,所以我想要更严格的验证。他们还没有注册。希望这是有道理的。
    • 您可能想使用new_record? (apidock.com/rails/ActiveRecord/Base/new_record%3F)
    • 最终,这取决于您的工作流程。您仍然有很多选择。我会用其他一些建议来更新这个问题。
    【解决方案2】:

    您可以使用conditional validation 例如:

    validates_presence_of :phone, :if => Proc.new { |p| p.lead? }
    

    【讨论】:

      【解决方案3】:

      在领导发布的任何操作中,您都可以这样做:

      @object.save(validate: false)
      

      然后,当他们需要签订合同时,不要使用 validate: false 选项以确保这些验证运行。

      此外,如果您只想跳过某些验证,请参阅 this post

      【讨论】:

      • 这看起来像我需要的。今晚我会试一试。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-27
      • 2021-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-23
      相关资源
      最近更新 更多