2013-04-24 10 views
5

Ich benutze Grails 2.2.1 und versuchen, eine verschachtelte Befehlsstruktur zu validieren. Hier ist eine vereinfachte Version meiner Befehlsobjekte:Grails validieren geschachtelten Befehl Objekt funktioniert nicht

@Validateable 
class SurveyCommand { 

    SectionCommand useful 
    SectionCommand recommend 

    SurveyCommand() { 
     useful = new SectionCommand(
       question: 'Did you find this useful?', 
       isRequired: true) 
     recommend = new SectionCommand(
       question: 'Would you recommend to someone else?', 
       isRequired: false) 
    } 
} 

@Validateable 
class SectionCommand { 
    String question 
    String answer 
    boolean isRequired 

    static constraints = { 
     answer(validator: answerNotBlank, nullable: true) 
    } 

    static answerNotBlank = { String val, SectionCommand obj -> 
     if(obj.isRequired) { 
      return val != null && !val.isEmpty() 
     } 
    } 
} 

Wenn ich versuche, eine Instanz von SurveyCommand zu validieren es gibt immer true egal die Abschnittswerte und meine benutzerdefinierten Validator in SectionCommand (answerNotBlank) nie aufgerufen. Aus der Grails-Dokumentation geht hervor, dass this kind of nested structure is supported (deepValidate standardmäßig auf true gesetzt ist). Vielleicht gilt diese Regel jedoch nur für Domänenobjekte und nicht für Befehlsobjekte? Oder verpasse ich hier gerade etwas?

Antwort

4

Sie könnten einen benutzerdefinierten Validator zu Ihrem Haupt-Befehlsobjekt hinzufügen

@Validateable 
class SurveyCommand { 

    SectionCommand useful 
    SectionCommand recommend 

    static subValidator = {val, obj -> 
     return val.validate() ?: 'not.valid' 
    } 

    static constraints = { 
     useful(validator: subValidator) 
     recommend(validator: subValidator) 
    } 

    SurveyCommand() { 
     useful = new SectionCommand(
      question: 'Did you find this useful?', 
      isRequired: true) 
     recommend = new SectionCommand(
      question: 'Would you recommend to someone else?', 
      isRequired: false) 
    } 
} 
+0

nett! Funktioniert großartig, aber gibt es einen TROCKENEN Weg, anstatt eine Einschränkung für jede Untereigenschaft explizit zu definieren? –

2

Wenn Sie versuchen, validation von unit Tests zu testen, mit mockForConstraintsTest() dann sollten Sie die command Objekte in Config.groovy registrieren anstelle von @Validateable wegen einer bestehende Grails Bug. Siehe hierzu SO question/answers für Details.

Sie können die validateable Klasse registrieren, wie unten in Config.groovy

grails.validateable.classes = 
      [yourpackage.SurveyCommand, yourpackage.SectionCommand] 
+0

es * scheint * gut zu funktionieren (in 2.2.1), um eine '.validate() '- Methode einer' @ Validatable'-Befehlsklasse zu testen, indem einfach' mockCommandObject' aufgerufen wird, bevor sie instanziiert wird, z. 'mockCommandObject SurveyCommand' –

+0

Zustimmen. Das war meine Herangehensweise an die SO-Frage/Antwort, die ich bereits erwähnt habe. 'mockCommandObject' funktioniert, aber' mockForConstraintsTest' schlägt fehl. – dmahapatro

+0

ah, hab es geschafft, danke fürs klären. Offensichtlich habe ich nicht nahe genug gelesen –

5

Für Grails 2.3 und später habe ich festgestellt, dass die Cascade Validation Plugin schön dieses Problem löst. Es definiert einen neuen Validierungstyp namens cascade, der genau das tut, was Sie erwarten würden. Einmal installiert wäre Ihr Beispiel:

class SurveyCommand { 
    ... 

    static constraints = { 
     useful(cascade: true) 
     recommend(cascade: true) 
    } 
}