【问题标题】:Running rails inclusion validation only if presence passes仅当存在通过时才运行 rails 包含验证
【发布时间】:2015-06-05 15:02:04
【问题描述】:

我想先验证一个字段是否存在,如果该字段没有值,则返回一条错误消息。然后假设此存在验证通过,我想运行包含验证。

现在我有:

validates :segment_type, presence: true, inclusion: { in: SEGMENT_TYPES }

我已尝试将其拆分为两个单独的验证,如下所示:

validates :segment_type, presence: true
validates :segment_type, inclusion: { in: SEGMENT_TYPES }

但问题在于上述两种尝试,当segment_type 字段中不包含任何值时,我都会收到两种响应的错误消息:

Segment type can't be blank
Segment type is not included in the list

在这种情况下,我只想要“Segment type can't be blank”而不是第二条消息。

有没有什么方法可以告诉 Rails 执行此条件验证并给我所需的错误消息瀑布,而无需我定义一个自定义函数,例如 segment_type_presence_and_inclusion_check,它依次检查这些条件并使用 @ 调用它987654326@?

【问题讨论】:

    标签: ruby-on-rails validation


    【解决方案1】:

    您还应该能够在包含验证中使用allow_blank

    validates :segment_type,
              presence: true,
              inclusion: { in: SEGMENT_TYPES, allow_blank: true }
    

    【讨论】:

    • 这比标记的答案更简单、更优雅。仅供参考,另见allow_nil: true。我认为这些是相关文档:apidock.com/rails/ActiveModel/Validations/ClassMethods/…
    • presence: true 在此处不再是必需的。此外,allow_blank 现在应该位于inclusion: {} 选项哈希的外部。 (edgeguides.rubyonrails.org/…)
    • 事实上 SEGMENT_TYPES 看起来像是一个用于枚举的整数字段,因此 allow_nil 是使用的选项,而不是 allow_blank。
    【解决方案2】:

    inclusion 选项中传入if 以检查是否存在

    validates :segment_type,
      presence: true,
      inclusion: { in: SEGMENT_TYPES, if: :segment_type_present? }
    
    private
    
    def segment_type_present?
      segment_type.present?
    end
    

    您也可以使用proc

    inclusion: { in: SEGMENT_TYPES, if: proc { |x| x.segment_type.present? } }
    

    【讨论】:

    • 这是否仅适用于inclusion:?我似乎无法用自定义验证器替换inclusion,因此我使用了下面的@michael-discenza 方法,但我觉得应该可以通过在模型上调用validates: 一次(而不是两次)来实现。跨度>
    • 不,它应该与其他验证助手一起使用。您要修复的代码是什么?
    • validates :title, presence: true, length: { maximum: 255 } validates :title, generate_url: true, if: proc { |p| p.title.present? && p.title.length <= 255 } 然后我在app/validators 中有一个GenerateUrlValidator
    • 啊……嗯不确定。以前从来没有机会这样做。你有没有试过validates :title, generate_url: { if: proc { |p| p.title.present? } }
    • Rails 使用你的属性名称+问号生成一个方法来测试值的存在。所以你可以简单地做segment_type?,它和segment_type.present?做的一样
    【解决方案3】:

    我发现这也有效。

    validates :segment_type, presence: true
    validates :segment_type, inclusion: { in: SEGMENT_TYPES }, if: "segment_type.present?" 
    

    【讨论】:

      猜你喜欢
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      • 2013-05-23
      • 2020-12-28
      • 2016-09-21
      相关资源
      最近更新 更多