tags:

views:

324

answers:

2

Hi,

In version 1.2, Grails introduced global constraints. I tried adding the following to Config.groovy

grails.gorm.default = {

    constraints {
        notBlank(nullable:false, blank:false)
    }
}

Then using it in one of my domain classes

static constraints = {
    email(email: true, unique: true, shared: 'notBlank')
}

But when I save a user with a null e-mail address, no errors are reported, why?

Thanks, Don

+3  A: 

I've never tried to make global constraints, but I can tell you that if you want to mark a field as not blank and not nullable you don't need to create a new constraint at all, just add this to your domain class:

static constraints = {
    email(blank:false)
}

Of course if you're expecting an exception on save you won't get one - you need to test the object after calling save() or validate() as demonstrated in this domain class:

class Contact {
    static constraints = {
        name(blank:false)
    }
    String name
}

and its test case:

import grails.test.*

class ContactTests extends GrailsUnitTestCase {
    protected void setUp() {
        super.setUp()
    }

    protected void tearDown() {
        super.tearDown()
    }

    void testNameConstraintNotNullable() {
        mockDomain Contact
        def contact = new Contact()
        contact.save()
        assertTrue contact.hasErrors()
        assertEquals "nullable", contact.errors["name"]
    }
}

If you do want exceptions on save, you can add this setting in your Config.groovy:

grails.gorm.save.failOnError = true

I found it to be quite useful in development.

HTH

PS

To use a constraint you've defined you'd need to add this to your domain class:

static constraints = {
    email(shared:"myConstraintName")
}

But be warned, you can't test the constraint in a unit test as you would the built in ones as the config will not have been read.

Dave
Thanks for the tip about not being able to unit test global contraints - didn't know that. BTW, why wouldn't you want failOnError turned on in prod too?
Don
I keep it turned off so that the default behaviour is to fail quietly to a log file rather than barf a big stack trace over the user's screen. There are other ways of achieving this of course and you'll probably have your own 500 error screen set up anyway, so I guess the answer is personal preference.
Dave
+1  A: 

If you want the default constraint applied to all properties is should be:

grails.gorm.default = {
    constraints {
        '*'(nullable:false, blank:false)
    }
}

If you want to name the constraint, you would apply it to your domain class property of email using the shared key:

static constraints = {
    email(email: true, unique: true, shared: "notBlank")
}

The default in grails is to not allow null properties, so blank:false is all you really need (i.e., global default you defined in this case is not needed).

John Wagenleitner