2

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

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('-')

但是,如果有人可以解释为什么会这样,但第一个不是,我会很感激。真正的问题是数据保存时没有破折号(在应用上述修复之后)。我在这里忘记或误解了一些基本的东西吗?有没有人对此有更好的解决方案?

谢谢,

4

2 回答 2

3

尝试

def validate_sn
  if !self.serialNumber.nil? && self.serialNumber !~ /-/
    self.serialNumber = self.serialNumber.scan(/.{4}/).join('-')
  end
end
于 2011-03-23T17:23:46.457 回答
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 过滤器中。

于 2011-03-23T17:45:36.223 回答