ActiveRecord getter中断验证

时间:2015-12-17 11:45:50

标签: ruby-on-rails ruby validation activerecord

我需要验证信用卡号。

model Billing
  validates :card, credit_card_number: true, allow_nil: true

验证宝石代码:

  def validate_each(record, attribute, value)
    record.errors.add(attribute, options[:message] || :invalid) unless credit_card_valid?(value, extract_brands(record, options))
  end

一切正常。 但后来我尝试用这种方式覆盖geter:

   def card
    "****#{self[:card][-4,4]}" if self[:card]
   end

验证失败。 当我猴子修补validates_each像那样:

  def validate_each(record, attribute, value)
    value = record[attribute]
    record.errors.add(attribute, options[:message] || :invalid) unless credit_card_valid?(value, extract_brands(record, options))
  end

它恢复运作良好。 验证getter而不是持久化值是否是正确的验证行为(validates_each第一个变体是遵循指南)。 或者什么是解决我的问题的优先方式? 更新:Activemodel / Activerecord版本:4.2.3

2 个答案:

答案 0 :(得分:1)

首先,您定义的方法不是模型关注点 - 它是一个视图关注点,因此应该移动到帮助器或演示者。然而,在模型中使用这些方法是非常常见的做法,所以我不会说这是一个很大的问题。

您可以通过选择方法的其他名称轻松解决整个问题:

def starred_card
  card && "****#{card[-4,4]}"
end

答案 1 :(得分:0)

当你覆盖getter方法时(正如你在这里所做的那样),你必须编写一个自定义验证方法。

例如,这是一个允许nil的简单验证,并确保卡号是一个16位的字符串。

validate :correct_credit_card_number

def correct_credit_card_number
    if self[:card] && self[:card] !~ /^\d{16}$/
        errors.add(:card, "is not in the right format")
    end
end