如何在Rails上处理依赖验证?

时间:2018-11-06 11:56:38

标签: ruby-on-rails ruby validation activerecord

我的模型上有一些Active Record验证:

function indexTraverseOnly<T extends Record<K, TraversableType & Record<K2,TraversableType& Record<K3,TraversableType>>>, K extends keyof any, K2 extends keyof any, K3 extends keyof any>(startObj: T, key: K, key2:K2, key3:K3): T[K][K2][K3]
function indexTraverseOnly<T extends Record<K, TraversableType & Record<K2,TraversableType>>, K extends keyof any, K2 extends keyof any>(startObj: T, key: K, key2:K2): T[K][K2] 
function indexTraverseOnly<T extends Record<K, TraversableType>, K extends keyof any>(startObj: T, key: K): T[K]
function indexTraverseOnly(startObj: any, ...key: string[]): any {
  return null; 
}

let t2: TypeTwo;

let r1 = indexTraverseOnly(t2, 'typeOne');     // TypeOne
let r2 = indexTraverseOnly(t2, 'typeOne', 'typeTwo'); // TypeTwo
let r3 = indexTraverseOnly(t2, 'typeOne', 'typeTwo', 'typeThree'); // TypeThree

那似乎很好。它验证字段class Product < ApplicationRecord validates :name, presence: true, length: { is: 10 } end 不是namenil,并且该字段必须正好包含10个字符。现在,如果要添加一个custom validation,我将添加一个""调用:

validate

问题是:当class Product < ApplicationRecord validates :name, presence: true, length: { is: 10 } validate :name_must_start_with_abc private def name_must_start_with_abc unless name.start_with?('abc') self.errors['name'] << 'must start with "abc"' end end end 字段为name时,nil验证将捕获它,但不会阻止它使用自定义方法{{1} },并以presence_ofname_must_start_with_abc的形式引发NoMethodError

要克服这一点,我必须在name方法上添加nil-check。

nil

那是我不想做的,因为如果我添加更多的“依赖”验证,则必须在每种自定义验证方法上重新进行验证。

如何在Rails上处理依赖验证?如果没有通过其他验证,是否可以防止调用自定义验证?

2 个答案:

答案 0 :(得分:1)

我认为,除非您将所有验证都编写为自定义方法,否则没有完美的解决方案。我经常使用的方法:

class Product < ApplicationRecord
  validates :name, presence: true, length: { is: 10 }
  validate :name_custom_validator

  private

  def name_custom_validator
    return if errors.include?(:name)

    # validation code
  end
end

这样,您可以向:name添加尽可能多的验证,如果其中任何一个失败,则您的自定义验证器将不会执行。但是这段代码的问题是您的自定义验证方法必须是最后一个。

答案 1 :(得分:-1)

class Product < ApplicationRecord
  validates :name, presence: true, length: { is: 10 }
  validate :name_must_start_with_abc, unless: Proc.new { name.nil? }

  private

  def name_must_start_with_abc
    unless name.start_with?('abc')
      self.errors['name'] << 'must start with "abc"'
    end
  end
end

请同时检查allow_blank:allow_nilconditional validation,以了解更多选项。