Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's say I have a collection that is setup in my controller, named "things." In this collection is a heterogeneous assortment of objects. Let's say some are of type "Thing" and some others are of type "OtherThing". In the GSP page that renders this list, I want to render each different object type differently.

I know that the following code works, but I can't escape the feeling that there should be a more elegant way to do this. Does anybody have a better way?

        <div id="eventStream">

        <ul>
            <g:each in="${things}" var="thing">

                <g:if test="${thing.type.equals( 'Thing' )}">
                    <g:render template="/renderThing" bean="thing" />
                </g:if>

                <g:if test="${thing.type.equals( 'OtherThing')}">
                    <g:render template="/renderOtherThing" bean="thing" />
                </g:if>

            </g:each>       
        </ul>

    </div>

(Note: there is a "type" field defined on 'Thing' and 'OtherThing' that contains those string literals. That's just a shortcut).

EDIT: Just realized that there's another way to do this, that depends on the notion of "convention over configuration." I could just go with a convention that the templates are always named something like:

_renderXXXXTemplate.gsp where XXX is "Thing" or "OtherThing" or whatever. Then I just render with something like:

<g:render template="/render${thing.class.name}Template" bean="thing" />

Anybody care to share their thoughts on the merit of that approach?

share|improve this question
add comment

1 Answer

I hate explicit type-checks. I would probably start by creating a private tag to render this part of the page.

<myApp:renderThing object="${thing}" />

Then I would probably add an abstract method to the base class to return the template name. Sure, it mixes presentation logic into the business classes but it will simplify maintenance considerably.

abstract class Thing {
    public abstract String getTemplateName();
    ...
}

public class ThingOne extends Thing {
    public String getTemplateName() { return "templateForThingOne" }
    ...
}

Another idea would be to derive the template name from the class name, and add a note in the base class to remind developers to create the appropriate template for any subclass.

share|improve this answer
    
OK, that's the other idea I had in mind as well. And, as you mention, it has the issue of mixing things across layers. That has a bit of a "code smell" to me, but I guess it's still cleaner than explicit type checks (which are exactly what I want to avoid). –  mindcrime Jan 29 '12 at 7:45
    
I don't mind adding code in the models to support presentation. Just don't add code in the models that does presentation. –  kevin cline Jan 30 '12 at 2:11
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.