Wednesday, May 5, 2010

Grails: Dynamically adding a save method to Domain objects that show errors

I was writing some integration tests and I noticed that one of my asserts was failing on a save. It was not clear to me why, so I started to add some diagnostic printing of errors. Then I thought - what happens if another domain object has a problem saving? Am I going to have to do this kind of error check all of the time? Ugh..

Using what I have already blogged about in terms of adding metaprogramming for Services, and a quick google search: See this link where I got most of the inspiration.

What I did was add the following method to Bootstrap.groovy.

  def addDebugSaveToDomainObjects() {
grailsApplication.domainClasses.each {
it.metaClass.debugSave = {
def obj = delegate.save()
if( obj == null ) {
println "Error saving " + delegate.getClass().name
delegate.errors.allErrors.each {
println it
}
}
return obj
}
}
}



The above code will add a new method to all Domain objects call debugSave. If there is a problem while saving the domain object this new method will print all of the errors. These errors can be seen in the junit reports.

I did it this way because I really only want these methods when I am testing and I did not want to clutter the domain API with this debug code.

In the bootstrap, I look at the environment and based on the environment name I will call the above closure ( or not as the case may be ).

Next in my integration test, I can execute code like the following:

def myDomain = new Domain(....)
assertNotNull myDomain.debugSave()

If the assert fails, then the Junit reports will tell me so and the output will tell me why.

I hope you found this information useful.