If I have a class with many properties that share identical attribute constraints like this:
class myClass {
String thisString
String thatString
String theOtherString
static constraints = {
thisString(nullable: true)
thatString(nullable: true)
theOtherString(nullable: true)
}
}
Is there an easier "one line" way to declare the static constraints? Something akin to say:
static constraints = {
thisString, thatString, theOtherString(nullable:true)
}
? Thank you.
Grails has something known as Global Constraints. This allows you to reuse identical constraints between many different GORM objects.
grails-app/conf/Config.groovy
grails.gorm.default.constraints = {
mySharedConstraint(nullable:true, ...)
}
myClass.groovy
class myClass {
String thisString
String thatString
String theOtherString
static constraints = {
thisString(shared: mySharedConstraint)
thatString(shared: mySharedConstraint)
theOtherString(shared: mySharedConstraint)
}
}
If you don't even want to to that...you can simply apply constraints to everything by doing something like this:
grails.gorm.default.constaints = {
'*'(nullable:true)
}
The start will apply this to all properties.
In the end, I would consult the link above. Good Luck!
Related
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.
First please go here
https://grails.github.io/grails-doc/3.0.x/guide/GORM.html#manyToOneAndOneToOne
If you scroll few lines, you'll see the line
Finally, it's a good idea to add a unique constraint on one side of the one-to-one relationship:
The code is
class Face {
static hasOne = [nose:Nose]
static constraints = {
nose unique: true
}
}
I took out the changelog of the following two domain definitions without the unique:true
class Nose {
String name
Cat cat
static constraints = {
}
}
class Cat {
String name
static hasOne = [nose: Nose]
static constraints = {
}
}
and the changelog shows that the unique has been added
<changeSet author="S (generated)" id="1452758231706-5">
<createIndex indexName="cat_id_unique_1452758231629" tableName="nose" unique="true">
<column name="cat_id"/>
</createIndex>
</changeSet>
So, although this is not a big deal to have few redundant statements in the docs i wanted to make sure that the unique:true is really not necessary. Specifying hasOne and having a back reference is enough to make the relationship truly one to one. Is that correct? Thanks!
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']
}
}
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.
I have a Grails domain called People, and I want to check that each People has childs or not. Childs are other People objects. Here is my domain structure:
class People implements Serializable {
static constraints = {
name (nullable : false, unique : true)
createdBy (nullable : false)
creationDate (nullable : false)
}
static transients = ['hasChild']
static mapping = {
table 'PEOPLE'
id generator: 'sequence', params : [sequence : 'SEQ_PK_ID']
columns {
id column : 'APEOPLE_ID'
parentPeople column : 'PARENT_PEOPLE_ID'
}
parentPeople lazy : false
}
People parentPeople
String name
String description
Boolean hasChild() {
def childPeoples = People.createCriteria().count {
eq ('parentPeople', People)
}
return (childPeoples > 0)
}
}
But I cannot call people.hasChild() at anywhere. Could you please helpe me on this? Thank you so much!
It's because in eq ('parentPeople', People), Grails can't understand what "People" is (it's a class). You should replace "People" by this. For example:
static transients = ["children"]
def getChildren() {
def childPeoples = People.findAllByParentPeople(this, [sort:'id',order:'asc'])
}
Another way to get the same result is to use Named Queries. It seems more concise and was created specifically for this purpose. I also like it because it fits the pattern of static declarations in a domain model and it's essentially a criteria, which I use throughout my applications. Declaring a transient then writing a closure seems a bit of a work-around when you can declare named queries ... just my opinion.
Try something like this:
static namedQueries = {
getChildren {
projections {
count "parentPeople"
}
}
}