Groovy

Grails domain classes and special presentation requirements

In Grails we often use our domain objects directly as backing model for presentation purposes and only for specialized situations we create value holder objects or DTOs.

Beginning Grails developers know how to display individual entity properties pretty easy in a GSP, such as the name of a fictional domain class…
 
 
 
 
 
 

<g:each in=”${breedingGoals}” var=”breedingGoal”>
  ${breedingGoal.name}
</g:each>

or

<g:select from="${breedingGoals}"
  optionKey="code" 
  optionValue="name" />

breeding-goal-name

but sometimes struggle when new presentational requirements come in and slightly more or combined information needs to be displayed. Special constructions are contrived, such as the following:

def list() {
  def breedingGoals = BreedingGoal.list()
  breedingGoals.each {
    it.name = it.name + " ("+ it.code + ")"
  }
  render view: “viewName”, model: [breedingGoals: breedingGoals]
}

to not only display the name any more, but also something else – e.g. its code. And that’s when things get hairy!

breeding-goal-name-and-code

This looks like a sensible way to get the new correct output in the browser. But it is not.

In this case entities are actually updated and leave the database in a very messed up state after a few iterations. This is the point where seasoned developers tell beginning developers not to continue down that road.

If you are one of the latter, read some of GORM’s persistence basics for some background first, and get back here for some guidelines you could use, in order of my personal preference.

My main rule of thumb is:

Do NOT replace data by a (re)presentational version of itself.

It’s not a fully comprehensive list, just to get you thinking about a few options taking our aforementioned BreedingGoal use case as an example.

If the information is contained within the object itself

and you have the object, just format it right on the spot.

<g:each in=”${breedingGoals}” var=”breedingGoal”>
  ${breedingGoal.name} (${breedingGoal.code})
</g:each>

A GSP is especially useful for presentation purposes. I would always try that first.

Some people still get confused of the various Grails tags which seem to accept “just 1 property” of the domain class being iterated over, such as select.

<g:select from="${breedingGoals}"
  optionKey="code" 
  optionValue="name + (code)? Arh! Now what?" />

Luckily, sometimes the tag author thought about this! In the case of select, optionValue can apply a transformation using a closure:

<g:select from="${breedingGoals}"
  optionKey="code" 
  optionValue="${{ it.name + ' (' + it.code + ')' }}"  />

If this new formatted information is needed on more places

to stay DRY you can put it in the object itself. In your domain class, add a getter:

String getNamePresentation() {
  name + " ("+ code + ")"
}

which can be called as it were a property of the object itself.

<g:each in=”${breedingGoals}” var=”breedingGoal”>
  ${breedingGoal.namePresentation}
</g:each>

If information is NOT in the object itself, but needs to be retrieved/calculated with some other logic

you can use a Tag Library.

class BreedingGoalTagLib {

  def translationService

  def formatBreedingGoal = { attrs ->
    out << translationService.translate(attrs.code, user.lang)
  }
}

In this example some kind of translationService is used to get the actual information you want to display.

<g:each in=”${breedingGoals}” var=”breedingGoal”>
  <g:formatBreedingGoal code=${breedingGoal.code} />
</g:each>

A TagLib is very easy to call from a GSP and has full access to collaborating services and the Grails environment.

If there’s no additional calculation necessary, but just special (HTML) formatting needs

Get the stuff and delegate to a template:

class BreedingGoalTagLib {

  def displayBreedingGoal = { attrs ->
    out << render(template: '/layouts/breedingGoal', 
      bean: attrs.breedingGoal)
  }
}

where the specific template could contain some HTML for special markup:

<strong>${it.name}</strong> (${it.code})

Or you need to initialize a bunch of stuff once or you’re not really aiming for GSP display

you could create a (transient) property and fill it upon initialization time.

Adjust the domain class, make your new “presentation” property transient – so it won’t get persisted to the database – and initialize it at some point.

class BreedingGoal {

  String code
  String name
  String namePresentation

  static transients = ['namePresentation']
}
class SomeInitializationService {

  // in some method...
  def breedingGoal = findBreedingGoal(...
  breedingGoal.namePresentation = 
    translationService.translate(breedingGoal.code, user.lang)

  return breedingGoal

}

Friendly word of advice: don’t try and litter your domain classes too much with transient fields for presentation purposes. If your domain class contains 50% properties with weird codes and you need the other half with associated “presentation” fields, you might be better off with a specialized value or DTO object.

Conclusion

You see there a various presentation options and depending on where the information comes from and where it goes to some approaches are better suited than others. Don’t be afraid to choose one and refactor to another approach when necessary, but I’d stick to the simplest option in the GSP first and try not to mangle your core data for presentation purposes too much!

Ted Vinke

Ted is a Java software engineer with a passion for Web development and JVM languages and works for First8, a Java Web development company in the Netherlands.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button