What is the correct way to do something like this with grails:
class myDomainThing {
String description
MyOtherDomainThing otherThing
static constraints = {
description(nullable:if(otherThing))
otherThing(nullable:if(description))
}
}
So I either want there to be a link to the otherDomainThing or I want a String description.
You will have to use Grails custom validation using the
validator
static constraints = {
description(validator: {
return otherThing and !description
})
}
you'll need to use a custom validator
static constraints = {
description validator: { val, obj ->
if(otherthing && val) {
false
}
else {
true
}
}
}
obviously some pseudocode in there around otherthing
Related
Is there some way to mock a domain field validator?
Currently, my code in the domain class is looking like this:
isPrimary(validator: { Boolean value, Person obj ->
.......
}
And I need to mock this function.
I tried to use it like:
Person.metaClass.static.isPrimary.validator = { Boolean value, Person obj ->
.......
}
And it didn't work, any suggestions how to solve this issue ?
Here is an example:
class Person {
Boolean isPrimary
static constraints = {
isPrimary validator: isPrimaryValidator
//or this for a fully qualified validator
//isPrimary validator: Person.isPrimaryValidator
}
static isPrimaryValidator = { Boolean value, Person obj ->
//some validation
}
}
//in Test
Person.metaClass.'static'.isPrimaryValidator = { Boolean value, Person obj ->
//Do something else
}
I have a Command Object as follows :
class TestCreationCommand {
String title
List testItems = [].withLazyDefault {new VocabQuestion()}
static constraints = {
title(blank:false,maxLength:150)
testItems( validator: { ti ->
ti.each {it.validate()}
} )
}
}
Test Items is a list of VocabQuestion objects. VocabQuestion is as follows :
class VocabQuestion {
static constraints = {
question(blank:false,maxLength:150)
answer(blank:false,maxLength:40)
}
static belongsTo = [vocabularyTest: VocabularyTest]
String question
String answer
}
I'm attempting to validate the constraints on the VocabQuestion using a custom vaildator ( in the constraints of the Command class above ), but I keep getting the following error message.
Return value from validation closure [validator] of property [testItems] of class [class vocabularytest.TestCreationCommand] is returning a list but the first element must be a string containing the error message code
I have had many different attempts at this .....
I am not sure what the message is telling me or how to go about debugging what the return value from the closure is.
Can anyone provide me any pointers?
You are not returning what Grails understands. You can't expect to just return anything and have Grails know what to do with it. Return a boolean or an error string.
static constraints = {
title(blank:false,maxLength:150)
testItems( validator: { ti ->
Boolean errorExists = false
ti.each {
if (!it.validate()) {
errorExists = true
}
}
errorExists
})
}
Check out this SO question It might be the format of the validator you need.
The .every will return a boolean.
Let's say I have the following model:
class Product {
String name
String price
String currency
static constraints = {
currency inList: ['USD', 'EUR']
}
Now we have a new requirement that inList constraint for currency must be pulled from a service:
class CurrencyService {
def getAvailableCurrencies = {
...
}
}
How do I make this work? I tried:
class Product {
def currencyService
...
static constraints = {
currency inList: currencyService.getAvailableCurrencies()
}
}
But I can't access the currencyService instance in the static constraints context. I also tried using static currencyService, but this likewise does not work. Any ideas?
As dmahapatro mentioned above, you could use a custom validator which uses your service:
static constraints = {
currency validator: { value, obj ->
if (!(value in obj.currencyService.getAvailableCurrencies()))
return ['invalid.currency']
}
}
My validation looks like:
static constraints =
{
someProperty validator: { val, obj ->
// a lot of code here
}
}
How can I define external function which will pass to this validation (val, obj requierd) ?
Now my code isn't clear in constraints closures... there's too much validation code for someProperty.
How can I change it?
By creating a groovy class in the src/groovy directory, like :
public class CustomValidators {
static validateMe = { val, obj ->
// a dummy example...
return val < 1
}
}
Then, on your domain class use it like below :
static constraints =
{
someProperty validator: CustomValidators.validateMe
}
I need to create a many-to-many relationship in Grails.
I have a "Question" domain and a "Tag" domain.
A Question can have 0 or more tags. A Tag can have 0 or more Questions.
If I put a "hasMany" on each sides, it gives me an error saying I need a "belongTo" somewhere.
However, adding a belongsTo means that the owner must exist...
Like I said, a Tag could have 0 questions, and a Question could have 0 tags.
There is no concept of an owner, it's a many-to-many!
What am I supposed to do?
you can do this (please see the code below). but does it make sense to have a question tag with out both a question and a tag?
package m2msansbt
class Question {
String toString() { return name }
String name
static hasMany=[questionTags:QuestionTag]
static constraints = {
}
}
package m2msansbt
class Tag {
String toString() { return name }
String name
static hasMany=[questionTags:QuestionTag]
static constraints = {
}
}
package m2msansbt
class QuestionTag {
Question question
Tag tag
static QuestionTag link(Question question,Tag tag) {
QuestionTag questionTag=QuestionTag.findByQuestionAndTag(question,tag)
if (!questionTag) {
questionTag = new QuestionTag()
question?.addToQuestionTags(questionTag)
tag?.addToQuestionTags(questionTag)
questionTag.save()
}
return questionTag
}
static void unlink(Question question,Tag tag) {
QuestionTag questionTag=QuestionTag.findByQuestionAndTag(question,tag)
if (questionTag) {
question?.removeFromQuestionTags(questionTag)
tag?.removeFromQuestionTags(questionTag)
questionTag.delete()
}
}
static constraints = {
}
}
import m2msansbt.*
class BootStrap {
def init = { servletContext ->
Question q1=new Question(name:'q1')
Tag t1=new Tag(name:'t1')
Tag t2=new Tag(name:'t2')
q1.save()
t1.save()
t2.save()
QuestionTag q1t1=QuestionTag.link(q1,t1)
q1t1.save()
QuestionTag q1t2=QuestionTag.link(q1,t2)
q1t2.save()
q1.save()
t1.save()
}
def destroy = {
}
}
If your main concern is the cascading delete, you can take a look at 5.5.2.9 in the grails docs to manually disable it for the mapping.
I haven't tried it, but I think the mappedBy property can be used to solve this.
Checkout the Taggable Plugin.
It seems to solve the problem you are having and you could look at the source code if you want to see how they modeled the relationship. BTW this plugin was originally created by Graeme Rocher who is the lead developer on Grails.
This works for me on Grails 2.4.4. Add a "belongsTo" with just the classname.
class Question {
String toString() { return name }
String name
static hasMany=[tags:Tag]
static constraints = {
}
}
class Tag {
String toString() { return name }
String name
static hasMany=[questions:Question]
static belongsTo = Question
static constraints = {
}
}