Grails validation problems with sets of data: only getting one error message for all errors in a set
- by Matt
Hi,
I'm trying to validate a domain class that has a number of subsets.
class IebeUser {
...
static hasMany = [openUserAnswers:OpenUserAnswer,
closedUserAnswers:ClosedUserAnswer]
}
class OpenUserAnswer {
OpenQuestion openQuestion
String text
static belongsTo = [user:IebeUser]
static constraints = {
openQuestion(nullable:false)
text(blank:false)
}
}
class ClosedUserAnswer {
ClosedQuestion closedQuestion
ClosedAnswer answer
static belongsTo = [user:IebeUser]
static constraints = {
closedQuestion(nullable:false)
answer(nullable:false)
}
}
A closed question has a set of predefined answers and an open question lets the user enter a freeform answer. All is well until I come to validate the object after entry in a form:
params: [closedUserAnswers[0].answer.id:, closedUserAnswers[0]:[answer:[id:], answer.id:], password:dfgdfgdf, openUserAnswers[0].text:gdfgdfgdfg, openUserAnswers[0]:[text:gdfgdfgdfg], _isOptedOut:, create:Continue, username:gdfgdfggdf, email:[email protected], closedUserAnswers[1].answer.id:, closedUserAnswers[1]:[answer:[id:], answer.id:], openUserAnswers[1].text:, openUserAnswers[1]:[text:], firstName:dfgdf, lastName:gdfgdfgd, action:save, controller:main]
The key bits being:
closedUserAnswers[0].answer.id:, closedUserAnswers[0]:[answer:[id:]
closedUserAnswers[1].answer.id:, closedUserAnswers[1]:[answer:[id:]
openUserAnswers[1].text:, openUserAnswers[1]:[text:]
In my tests I have two objects of type closedUserAnswers and two of openUserAnswers. But when I call validation on IebeUser I only get validation errors for the closedUserAnswers or the openUserAnswers as a whole. I don't get validation errors for each object with a problem which is what I need. I really need an error per instance. Does anyone know what I'm doing wrong? Even when I call the validate method against each closedUserAnswer/openUserAnswer I still only get one per type.
Here are my errors. Sorry for all the code, but thought I'd include as much of the code as possible so that it makes sense.
Field error in object 'uk.co.cascaid.iebe.IebeUser' on field 'openUserAnswers.text': rejected value []; codes [uk.co.cascaid.iebe.OpenUserAnswer.text.blank.error.uk.co.cascaid.iebe.IebeUser.openUserAnswers.text,uk.co.cascaid.iebe.OpenUserAnswer.text.blank.error.openUserAnswers.text,uk.co.cascaid.iebe.OpenUserAnswer.text.blank.error.text,uk.co.cascaid.iebe.OpenUserAnswer.text.blank.error,openUserAnswer.text.blank.error.uk.co.cascaid.iebe.IebeUser.openUserAnswers.text,openUserAnswer.text.blank.error.openUserAnswers.text,openUserAnswer.text.blank.error.text,openUserAnswer.text.blank.error,uk.co.cascaid.iebe.OpenUserAnswer.text.blank.uk.co.cascaid.iebe.IebeUser.openUserAnswers.text,uk.co.cascaid.iebe.OpenUserAnswer.text.blank.openUserAnswers.text,uk.co.cascaid.iebe.OpenUserAnswer.text.blank.text,uk.co.cascaid.iebe.OpenUserAnswer.text.blank,openUserAnswer.text.blank.uk.co.cascaid.iebe.IebeUser.openUserAnswers.text,openUserAnswer.text.blank.openUserAnswers.text,openUserAnswer.text.blank.text,openUserAnswer.text.blank,blank.uk.co.cascaid.iebe.IebeUser.openUserAnswers.text,blank.openUserAnswers.text,blank.text,blank]; arguments [text,class uk.co.cascaid.iebe.OpenUserAnswer]; default message [Property [{0}] of class [{1}] cannot be blank]
Field error in object 'uk.co.cascaid.iebe.IebeUser' on field 'closedUserAnswers.answer': rejected value [null]; codes [uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable.error.uk.co.cascaid.iebe.IebeUser.closedUserAnswers.answer,uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable.error.closedUserAnswers.answer,uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable.error.answer,uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable.error,closedUserAnswer.answer.nullable.error.uk.co.cascaid.iebe.IebeUser.closedUserAnswers.answer,closedUserAnswer.answer.nullable.error.closedUserAnswers.answer,closedUserAnswer.answer.nullable.error.answer,closedUserAnswer.answer.nullable.error,uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable.uk.co.cascaid.iebe.IebeUser.closedUserAnswers.answer,uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable.closedUserAnswers.answer,uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable.answer,uk.co.cascaid.iebe.ClosedUserAnswer.answer.nullable,closedUserAnswer.answer.nullable.uk.co.cascaid.iebe.IebeUser.closedUserAnswers.answer,closedUserAnswer.answer.nullable.closedUserAnswers.answer,closedUserAnswer.answer.nullable.answer,closedUserAnswer.answer.nullable,nullable.uk.co.cascaid.iebe.IebeUser.closedUserAnswers.answer,nullable.closedUserAnswers.answer,nullable.answer,nullable]; arguments [answer,class uk.co.cascaid.iebe.ClosedUserAnswer]; default message [Property [{0}] of class [{1}] cannot be null]