2012-07-14 50 views
5

我有一个问题,我的域类有两个潜在的互斥外部键,序列号或传统查找值。如何为Grails域类中的两个字段创建和异或验证?

因为我不确定哪一个我会有任何给定的条目,我已经让他们都可以为空,并添加自定义验证,以确保我有一个且只有一个值。

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 

我是什么失踪?

回答

9

有多次的每个属性是没有必要的;实际上你只需要其中一个实际上受到限制。你也不能直接通过名字来引用属性。有些对象被传递给约束闭包,用于获取值(请参阅docs)。也许我发现做到这一点最简单的方法如下:

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... 

你并不需要从约束返回什么,如果没有错误...

+0

这正是我所需要的。我在想,我需要在两个领域明确验证,但一个处理另一个领域。谢谢! – GeoGriffin 2012-07-15 02:21:17

0

如果你想确保你有“唯一的一个值”,另一个选择是制作一个名为serialNumberLegacyLookup的通用字段,它将代表serialNumberlegacyLookup字段。然后,您可以将一个布尔型字段添加到您的域名类legacyLookup,该域默认为false。然后,您可以通过验证程序运行该值,并解析它以查看它是否为“序列号”或“传统查找”值。如果该值成为“传统查找”值,那么您将legacyLookup布尔值设置为true。我认为这种方法从UI角度来看不会让人困惑(只有一个字段供用户填写,而不是两个条件字段)。

+0

由于我正在使用的代码与外部遗留系统交互,我认为这种解决方案并不合适。收到的数据有一个字段或另一个字段,但它们被建模为独特的字段。可能有一些我现在未知的业务规则可能会破坏我对该模型的理解。为了让自己远离这种可能性,我会把他们分开。 – GeoGriffin 2012-07-15 02:19:49

0

我面临着这种相同的情况下,我找到了解决方案是创建一个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) 
    } 
} 
相关问题