[英]How do I create and XOR validation for two fields in a Grails domain class?
我有一个问题,我的域类有两个潜在的互斥外部密钥,序列号或遗留查找值。
由于我不确定任何给定条目我将拥有哪一个,我已经使它们都可以为空并添加自定义验证以确保我只有一个值。
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
我错过了什么?
在那里多次拥有每个财产是没有必要的; 实际上你只需要其中一个实际受约束。 此外,您不能直接通过名称引用属性。 传递给约束闭包的对象用于获取值(请参阅文档 )。 可能我发现这样做最简单的方法如下:
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中有两条消息:
only.one=Don't fill out both
must.be.one=Fill out at least one...
如果没有错误,您不需要从约束中返回任何内容......
如果你想确保你有“一个且只有一个值”,另一个选择是创建一个名为serialNumberLegacyLookup
的通用字段,它代表serialNumber
和legacyLookup
字段。 然后你可以在域类中添加一个名为legacyLookup
的布尔字段,默认为false
。 然后,您可以通过验证程序运行该值并对其进行解析,以查看它是“序列号”还是“遗留查找”值。 如果该值被证明是“遗留查找”值,那么您将legacyLookup
boolean设置为true
。 我认为从UI的角度来看,这种方法会更少混淆(用户只需填写一个字段而不是两个条件字段)。
我遇到了同样的情况,我找到的解决方案是创建一个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)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.