仅在所有其他validation通过时执行一次validation

我正在构建一个自定义validation,用于检查银行帐号并使用外部API 对代码进行排序 ,以测试它们是否存在(即是一个正确的有效英国银行帐户)。 由于这是一项昂贵的操作,我不想打扰API,除非帐号和排序代码通过Rails内置的validation。

例如,我有这些基本的validation:

validates_presence_of :sort_code, :account_number validates_format_of :sort_code, :with => Regexes::SORT_CODE validates_format_of :account_number, :with => Regexes::ACCOUNT_NUMBER 

然后我有自定义validation:

 validate :check_valid_bank_account def check_valid_bank_account # code here is irrelevant, but essentially this hits the API # if it's a valid UK bank account all is OK, if not we add an error end 

我想要确保的是,只有在模型的其余部分有效时才执行自定义validation。 当我能够自己解决这个问题时,没有任何一点支付25p被告知没有提供帐号!

我知道我可以编写一些逻辑来检查这两个属性是否为空并且手动将它们与正则表达式相匹配……但这似乎不是一种非常Rails的方式。

您可以检查errors数组并返回。

 def check_valid_bank_account return unless errors.blank? … end 

我实际上建议从validation方法中取出这些代码并将其放入单独的“valid_bank_account”中。 您实际想要访问API时可以手动调用的方法,尤其是因为这是一项昂贵的操作。 此行为的一些原因是,如果帐号未更改或者您只是更新记录,则可能不希望运行此validation。

 def save_only_with_valid_bank_account
   if @ account.valid?  && @ account.valid_bank_number?  && @ account.save
    ...
  结束
结束

它更乏味但它确保您可以控制validation何时实际发生。

使用这样的东西

 validates_presence_of :sort_code, :account_number validates_format_of :sort_code, :with => Regexes::SORT_CODE validates_format_of :account_number, :with => Regexes::ACCOUNT_NUMBER validate :check_valid_bank_account, :if => :should_i_call_custom_validation? def should_i_call_custom_validation? # check for attributes or errors, errors.empty? should work end 

Proc也应该在这里工作

 validate :check_valid_bank_account, :if => Proc.new{|object| object.errors.empty?}