How to "inherit" constraints from trait? - grails

I have a trait and the following domain classes:
trait Named {
String name
static constraints = {
name blank:false, unique:true
}
}
#Entity
class Person implements Named {
String fullName
static constraints = {
fullName nullable:true
}
}
#Entity
class Category implements Named {
}
In this setup the Named.constraints are working fine for Category, but are ignored for Person.
How can I include the constrains from a trait in a constraints block of an implementing domain class?

How can I include the constrains from a trait in a constraints block
of an implementing domain class?
The framework doesn't support it.

I found the least painful way to re-use the constraints.
I added a new class:
class CommonConstraints {
static name = {
name blank:false, unique:true
}
}
Then instead of importFrom Named which didn't work, I sprinkle some groovy magic:
#Entity
class Person implements Named {
String imgUrl
String fullName
static constraints = {
CommonConstraints.name.delegate = delegate
CommonConstraints.name()
fullName blank:false, unique:true
imgUrl url:true
}
}
And it works like charm.
Yes, the solution not consistent with inheritance/implementation model, but gets the job of code reuse done.
For the less tricky cases, where the domain class does not have it's own constraints, the ones from a trait will be used, like in my original question.

Related

How to set unique constraint in a hasMany relationship

I have this class:
class Word {
String word
static hasMany = [group: WordGroup]
static belongsTo = [language: Language]
static constraints = {
word(unique: ['language'], maxSize:255)
}
}
Which is working fine, but I would need to associate the unique constraint to both language and group, so different groups can insert the same "word".
The groups are in an intermediate table (WordGroup) as this is a many to many relationship.
If I try to do
word(unique: ['language', 'group'], maxSize:255)
I get the error
Missing IN or OUT parameter in index:: 3
Is there a way to do this?
EDIT: I am adding the other classes referenced in the Word class if it helps
WordGroup
class WordGroup {
static belongsTo = [word: Word, group: Group]
static constraints = {}
}
Group
class Group {
String name
String url
static hasMany = [words: Word]
static constraints = {
name blank: false, unique: true
}
}
Language
class Language {
String name
String code
static constraints = {
name maxSize:255
code maxSize:255
}
}
Thanks.

Creating Domain Relationships in Grails returns unable to resolve class error

Good day to all. I am very new in using grails and I have followed several tutorials for beginners using grails until I come up in creating domain relationships. However, I got stuck with this problem right now. I have 3 domain classes namely, todo, category and user. And as I defined their relationships, it returns me an error saying unable to resolve class. Please see my codes below. Please help. Thank you so much.
Todo.groovy Class
package todoScaff
class Todo {
String name
String note
Date createDate
Date dueDate
Date completedDate
String priority
String status
User owner
Category category
static belongsTo = [User, Category]
static constraints = {
name(blank:false)
createDate()
priority()
status()
note(maxsize:1000, nullable:true)
completedDate(nullable:true)
dueDate(nullable:true)
}
String toString() {
name
}
}
Category.groovy Class
package categoryScaff
class Category {
String name
String description
User user
static belongsTo = User
static hasMany = [todos: Todo]
static constraints = {
name(blank:false)
}
String toString(){
name
}
}
User.groovy Class
package userScaff
class User {
String userName
String fname
String lname
static hasMany = [todos: Todo, categories: Category]
static constraints = {
userName(blank:false, unique:true)
fname(blank:false)
lname(blank:false)
}
String toString(){
"$lname, $fname"
}
}
Since you've placed your domain classes in different packages, you must import the classes at the head of the file.
package categoryScaff
import todoScaff.Todo
import userScaff.User
class Category {
The same needs to happen in your other domain classes that reference classes outside the current package.

How do you organize the fields in grails 2.4.4 including the static mapping relations?

Okay, so I understand how to organize the fields in grails without using the gsp pages by writing the fields in the constraints like so.
Class User{
String firstName;
String nickName;
static constraints = {}
}
this will make first name appear before nick name in the default scaffolding because f comes before n in the alphabet.
Class User{
String firstName;
String nickName;
static constraints = {
nickName()
firstName()
}
}
this makes nick name appear before first name in the CRUD model in scaffolding. It's the order you name the constraints.
Now, how do you make the relations appear in a specific order? For example if I had this
Class User{
String firstName;
String nickName;
static belongsTo = {company:Company}
static constraints = {
}
}
How would I rearrange this order? would it be done in constraints? I know it can be done in gsp page, but how would I do it here?
I'm pretty sure it's the same as regular fields...
i.e. if you want the order of the fields to appear as nickName, firstName, company you'd do this:
Class User {
String firstName
String nickName
static belongsTo = {company: Company}
static constraints = {
nickName()
firstName()
company()
}
}

domain class constraint in entry creation

In my Grails project I need to add a particular constraint to an entry of my domain class object.
Domain class is as follows:
class HealthServiceType {
String healthService;
static belongsTo = [doctor:Doctor]
static constraints = {
}
static mapping = {
}
}
I need that healthService is not empty and is unique for each Doctor; that is, I can have multiple "test" value for healthService, but each one need to have different Doctor value.
Is it possible to perform this constraint in domain class? Or do I need to implement some check in Controller?
That's quite simple to make a unique property. For example:
static constraints = {
healthService(unique: ['doctor'])
}
The above will ensure that the value of healthService is unique for each value of doctor within your domain class.

Import domain in constraints

I have 2 domain classes
class a {
String name
static constraints = {
name unique:true
}
}
class b {
String description
}
and in domain class b I want to call class a
import a
class b {
String description
static constraints = {
description unique:'a.name'
}
}
and get error
Scope for constraint [unique] of property [description] of class [b] must be a valid property name of same class
How do I get a property from class a to b?
Assuming you try to do this in Grails 2+
You can't use validation that way. In your example you need to reference to a property of the same domain class. To correct the constraint in class B you can write:
class B {
String description
static contraints = {
description unique:true
}
}
But I think you want to import the constraints from class a which is done like this.
class B {
String description
static contraints = {
importFrom A
}
}
See http://grails.org/doc/latest/guide/validation.html#sharingConstraints
This will import all constraints on properties that the two classes share. Which in your case is none.
UPDATE
I got a similar question and found a solution for it. So I thought to share it here with you.
The problem can be solved with a custom validator. In your case constraints for class B:
static constraints = {
description(validator: {
if (!it) {
// validates to TRUE if the collection is empty
// prevents NULL exception
return true
}
def names = A.findAll()*.name
return names == names.unique()
})
}
It's difficult to answer your question correctly since the requirements are a bit odd. But maybe it will help.
You need to write a custom validator to check the uniqueness since it relies on more information than the single instance of b will have.
Something like
static constraints {
description validator: { val ->
!a.findByName(val)
}
}
might do the trick.

Resources