2012-08-29 57 views
0

我試圖在Squeryl中創建自定義字段類型。該字段代表Isin code,所以它由一個字符串字段進行備份。繼example on the documentation,我已經創造了新的ISIN前添加了一個簡單的驗證(別提了ISIN編碼是什麼,或者驗證程序的工作原理):Squeryl自定義字段類型

trait Domain[A] { self: CustomType[A] => 
    def validate(a: A): Unit 

    validate(value) 
} 

class Isin(v: String) extends StringField(v) with Domain[String] { 
    println("instantiating Isin") 
    override def validate(s: String) { 
    println("calling validate with " + s) 
    assert(checkIsin(s)) 
    } 

    private def checkIsin(isin: String): Boolean = { 
    // never mind the exact procedure 
    } 
} 

我增加了一些println找出是怎麼回事。我用這個域的模型裏面像

case class Asset(
    val id: Long = 0, 
    val isin: Isin 
) extends KeyedEntity[Long] 

object Asset { 
    import Database.assets 

    def create(isinCode: String) { 
    inTransaction { 
     assets.insert(new Asset(isin = new Isin(isinCode))) 
    } 
    } 
} 

現在,當我打電話Asset.create("US0378331005")(有效ISIN)我得到一個異常。在堆棧跟蹤中,事實證明,這個例外是由於init方法對null值的調用,該值應該被傳遞給checkIsin。事實上,println報表打印

calling validate with US0378331005 
Instantiating Isin 
calling validate with 

如此看來,該validate方法實際調用兩次,但第二次就得到一個null值。

這是怎麼回事?

回答

1

這裏有幾個問題。首先,你似乎在使用Lift Record,如果是這樣的話,你就錯誤地實現了你的驗證邏輯。驗證一個記錄字段的正確方法是重寫

def validations: List[ValidationFunction] 

其中ValidationFunction是一個類型別名

type ValidationFunction = ValueType => List[FieldError] 

,並在你的情況的ValueType ==字符串。

下一個問題是您的域特徵。因爲您的驗證調用內聯到類定義中,所以在構建字段時將調用它。很明顯,在這一點上沒有設置值,所以這就是爲什麼你看到引用一個空值的println。我想象你看到他們的順序與你的應用程序流程有關。您有一個已驗證的現有記錄,然後創建一個新記錄,該記錄觸發下兩個println語句。

相關問題