2012-07-14 1 views
5

도메인 클래스에 상호 배타적 인 두 개의 외부 키, 일련 번호 또는 레거시 조회 값이있는 문제가 있습니다.Grails 도메인 클래스의 두 필드에 대한 유효성 검사 및 XOR 검증을 어떻게 작성합니까?

주어진 입력에 대해 어느 것이 있는지 알 수 없으므로 입력 가능 여부를 확인하고 사용자 지정 유효성 검사를 추가하여 하나의 값만 가질 수 있도록했습니다.

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 

아니면 별도의 메시지를 가질 수 다음과 같이 아마 내가이 일을 발견했습니다 가장 간단한 방법은 message.properties에 두 개의 메시지가 다음

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

과 :

- 각 조건은 모두 입력, 또는 둘 모두는 다음과 같이 비어 있습니다
only.one=Don't fill out both 
must.be.one=Fill out at least one... 
나는이 같은 시나리오와 내가 찾은 솔루션에 직면했다
+0

이것은 정확히 내가 필요로했던 것입니다. 나는 두 필드 모두에서 명시 적으로 유효성 검사가 필요하다고 생각했지만 하나는 다른 필드를 처리합니다. 감사! – GeoGriffin

0

"하나 뿐인 값"을 보장하려면 serialNumberLegacyLookup이라는 일반 필드를 만들어 serialNumberlegacyLookup 필드를 모두 나타내는 옵션이 필요합니다. 그런 다음 legacyLookup이라는 도메인 클래스에 부울 필드를 추가 할 수 있습니다. 기본값은 false입니다. 그런 다음 유효성 검사기를 통해 값을 실행하고 구문 분석하여 "일련 번호"또는 "레거시 조회"값인지 확인할 수 있습니다. 값이 "레거시 조회"값으로 밝혀지면 legacyLookup 부울을 true으로 설정합니다. 나는이 접근법이 UI 관점 (사용자가 두 개의 조건부 필드 대신에 채울 수있는 하나의 필드)에서 덜 혼란 스러울 것이라고 생각한다.

+0

내가 작업하고있는 코드는 외부 레거시 시스템과 상호 작용하므로이 솔루션이 적절하다고 생각하지 않습니다. 내게 오는 데이터에는 하나의 필드 또는 다른 필드가 있지만 고유 한 필드로 모델링됩니다. 이시기에 알려지지 않은 일부 비즈니스 규칙이 모델에 대한 나의 이해를 손상시킬 수 있습니다. 그 가능성으로부터 자신을 보호하기 위해, 나는 그들을 분리시켜 둘 것입니다. – GeoGriffin

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) 
    } 
}