0

Squeryl でカスタム フィールド タイプを作成しようとしています。このフィールドはIsin コードを表すため、文字列フィールドによってバックアップされます。ドキュメントの例に従って、新しい isin を作成する前に簡単な検証を追加しました (Isin コードが何であるか、または検証手順がどのように機能するかは気にしないでください)。

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メソッドの呼び出しによるものであることがわかります。実際、ステートメントは印刷されますnullcheckIsinprintln

calling validate with US0378331005
Instantiating Isin
calling validate with

したがって、validateメソッドは実際には 2 回呼び出されているように見えますが、2 回目はnull値を取得します。

何が間違っているのですか?

4

1 に答える 1

1

ここにはいくつかの問題があります。まず、Lift Recordを使用しているようですが、その場合は、検証ロジックを正しく実装していません。レコードフィールドを検証する正しい方法は、オーバーライドすることです

def validations: List[ValidationFunction]

ここで、ValidationFunctionはタイプエイリアスです

type ValidationFunction = ValueType => List[FieldError]

あなたの場合、ValueType==Stringです。

次の問題はあなたのドメイン特性です。検証の呼び出しはクラス定義にインライン化されているため、フィールドが作成されるときに呼び出されます。明らかに、その時点では値が設定されていないため、空の値を参照するprintlnが表示されます。それらが表示される順序は、アプリケーションフローと関係があると思います。検証された既存のレコードがあり、その後、次の2つのprintlnステートメントをトリガーする新しいレコードが作成されます。

于 2012-09-03T21:06:09.393 に答える