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

但是,如果有人可以解釋爲什麼工作,但先不我將不勝感激。真正的問題是數據保存時沒有破折號(在應用上述修正之後)。我是否忘記或誤解了這裏的根本?有沒有人有更好的解決方案呢?

感謝,

+5

稍微偏離了觀點,但是您是否考慮過使用before_save過濾器,而不是在驗證中修改數據? – Yule 2011-03-23 17:27:54

+0

謝謝,很好的建議。 – Segfault 2011-03-23 17:34:47

回答

3

嘗試

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

是的,這是問題所在。謝謝。 – Segfault 2011-03-23 17:35:34

1

,因爲你是在兩個不同的上下文中使用SERIALNUMBER第一種方式是行不通的。

在這一行

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

你使用的方法SERIALNUMBER,因爲這種方法不存在,紅寶石將委託給method_missing方法將得到來自@屬性的哈希值。

但是,在這一行:你用你剛剛宣佈的serialNumber變量

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

。這個變量當然是零。實現你想要什麼的 一種方法是:

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

但作爲另一個用戶已經說過,在驗證修改數據是不是一個好的做法。所以,這段代碼應該在before_save過濾器中。