使用rails自定义验证来修改数据

时间:2011-03-23 17:20:18

标签: ruby-on-rails ruby ruby-on-rails-3 preprocessor customvalidator

我想在我的模型中添加一些逻辑,以确保在设备数据库中存在序列号的一致字符串表示。下面是我正在考虑的事情的一个示例:调用自定义验证并对对象中的数据进行格式化,然后将其保存到数据库中。

class Device < ActiveRecord::Base
  validates_presence_of :serialNumber
  validate :validate_sn
  def validate_sn
    if !serialNumber.nil? && serialNumber !~ /-/
      serialNumber = serialNumber.scan(/.{4}/).join('-')
    end
  end
end

我在使用此代码时遇到两个问题。首先,它会抛出一个错误

NoMethodError: undefined method `scan' for nil:NilClass
第6行,这对我来说很困惑。我可以通过将该行更改为:

来解决此问题
sn = serialNumber; serialNumber = sn.scan(/.{4}/).join('-')

但如果有人可以解释为什么会有效,但第一次不能解释它。真正的问题是数据是在没有破折号的情况下保存的(在应用上述修复之后)。我忘记或误解了一些基本的东西吗?有人有更好的解决方案吗?

谢谢,

2 个答案:

答案 0 :(得分:3)

尝试

def validate_sn
  if !self.serialNumber.nil? && self.serialNumber !~ /-/
    self.serialNumber = self.serialNumber.scan(/.{4}/).join('-')
  end
end

答案 1 :(得分:1)

第一种方法不起作用,因为您在两个不同的上下文中使用serialNumber。

在这一行

if !serialNumber.nil? && serialNumber !~ /-/

你正在使用方法serialNumber,因为这个方法不存在,ruby将委托给method_missing,它将从@attributes哈希中获取值。

但是,在这一行:

serialNumber = serialNumber.scan(/.{4}/).join('-')

您正在使用刚刚声明的serialNumber变量。这个变量当然是零。 实现目标的一种方法是:

self.serialNumber = self.serialNumber.scan(/.{4}/).join('-')

但另一位用户已经说过,在验证中修改数据并不是一个好习惯。所以,这段代码应该在before_save过滤器中。