5

ドメインクラスに、シリアル番号またはレガシールックアップ値の2つの潜在的な相互に排他的な外部キーがあるという問題があります。

特定のエントリにどちらを使用するかわからないため、null許容にし、カスタム検証を追加して、値が1つしかないことを確認しました。

package myproject 

class Sample {

    String information
    String legacyLookup
    String serialNumber

    static constraints = {
        information(nullable: true)
        legacyLookup(nullable: true)
        serialNumber(nullable: true)

        legacyLookup validator: {
            return ((serialNumber != null && legacyLookup == null) || (serialNumber == null && legacyLookup != null))
        }

        serialNumber validator: {
            return ((serialNumber != null && legacyLookup == null) || (serialNumber == null && legacyLookup != null))
        }
    }
}

デフォルトのCRUD画面を作成し、このドメインクラスのエントリを作成しようとしました

information: Blah Blah
serialNumber: 
legacyLookup: BLAHINDEX123

これは、次のメッセージでバリデーターで終了します。

No such property: serialNumber for class: myproject.Sample

私は何が欠けていますか?

4

3 に答える 3

9

各プロパティを複数回持つ必要はありません。実際、実際に制約されているのはそのうちの1つだけです。また、プロパティを名前で直接参照することはできません。値を取得するために使用される制約クロージャに渡されるオブジェクトがあります(ドキュメントを参照)。おそらく、これを行うために私が見つけた最も簡単な方法は次のとおりです。

class Sample {
    String information
    String legacyLookup
    String serialNumber

    static constraints = {
        information(nullable: true)
        legacyLookup(validator: {val, obj->
            if( (!val && !obj.serialNumber) || (val && obj.serialNumber) ) {
                return 'must.be.one'
            }
        })
    }
}

そして、messages.propertiesファイルに次のようなエントリがあります。

must.be.one=Please enter either a serial number or a legacy id - not both

または、条件ごとに個別のメッセージを設定することもできます。両方を入力するか、次のように両方を空白にします。

legacyLookup(validator: {val, obj->
    if(!val && !obj.serialNumber) {
         return 'must.be.one'
    }
    if(val && obj.serialNumber) { 
         return 'only.one'
    }
})

そして、message.propertiesに2つのメッセージがあります。

only.one=Don't fill out both
must.be.one=Fill out at least one...

エラーがなければ、制約から何も返す必要はありません...

于 2012-07-14T06:20:13.833 に答える
0

「唯一の値」があることを確認したい場合、別のオプションは、とフィールドserialNumberLegacyLookupの両方を表すと呼ばれる汎用フィールドを作成することです。次に、デフォルトで。と呼ばれるドメインクラスにブールフィールドを追加できます。次に、バリデーターを介して値を実行し、それを解析して、それが「シリアル番号」または「レガシールックアップ」値であるかどうかを確認できます。値が「レガシールックアップ」値であることが判明した場合は、ブール値をに設定します。このアプローチは、UIの観点からはそれほど混乱しないと思います(2つの条件付きフィールドではなく、ユーザーが入力できるフィールドは1つだけです)。serialNumberlegacyLookuplegacyLookupfalselegacyLookuptrue

于 2012-07-14T04:32:30.090 に答える
-1

私はこれと同じシナリオに直面しました。私が見つけた解決策は、getterメソッドを作成し、それに制約を追加することでした。

package myproject 

class Sample {

    String information
    String legacyLookup
    String serialNumber

    def getTarget(){
        if (legacyLookup && !serialNumber) {
            return legacyLookup
        } else if (!legacyLookup && serialNumber) {
            return serialNumber
        } else {
            return null
        }
    }

    static constraints = {
        information(nullable: true)
        legacyLookup(nullable: true)
        serialNumber(nullable: true)
        target(nullable: false)
    }
}
于 2017-09-22T19:00:19.183 に答える