I have a fairly straight-forward model of users with profiles and experts, who are special users:
class User { static hasOne = [profile: Profile] }
class Profile {
String country
static constraints = { country nullable: true, blank: true }
}
class Expert extends User {
static constraints = {
profile validator: { val, obj ->
if (!val.country) {
val.errors.rejectValue 'country', 'expert.profile.country.nullable'
}
}
}
}
When I create an expert, set their profile properties and then save the expert, this works as it should. However, if a user wants to save their profile, I am stuck with how to properly validate the profile properties depending on whether they are an expert or not.
This is what I have so far:
Expert expert = Expert.get(profile.user.id)
if (expert) {
expert.properties = params
expert.save()
} else {
profile.user.properties = params
profile.user.save()
}
This code does the proper validation and sets the correct error message. However, there are (at least) three issues:
What is the proper way to validate an inherited domain class attribute? Alternatively, is there a better model that I could use to accomplish the goal of different types of users with role-specific validation requirements?
EDIT: It turned out that only the first of the three issues was real. The other two were caused by a tag lib saving the user object while trying to query the DB. The accepted solution (validation in Profile
based on a user flag) addresses that.
I think you have to set that the profile belongs to an user, and could be nullable. After that you can create the validator inside the profile class. Maybe for you the expert type needs a new class, but i am not sure if that is compulsory.
Maybe I could implement a method inside the User class to know if an entity is an expert based on its properties, or a property itself
class User {
static hasOne = [profile: Profile]
boolean expert
}
class Profile {
static belongsTo = [user: User]
String country
static constraints = {
country validator: { val, obj ->
if (obj.user?.expert && !val.country) {
val.errors.rejectValue 'country', 'expert.profile.country.nullable'
}
}
user nullable: true
}
}