Sunday, September 27, 2009

Getting data into Grails tags and templates

In the post describing how to create and use grails templates and tags I made short example that showed how gsp pages can be readable if you are using tags and templates. One of the questions asked in comments was how do I get data into tag and/or template. Instead writing answer as comment I decided to write the whole post.

Scoped variables
Common way to get data into tag and template is using Grails scoped variables like application, session, request. This means that both, tags and templates, have access to those variables so you can use them.

Templates
To send data into templates you can and should use standard approach with the grails model.

For example if you are rendering template from tag or from controller (or some groovy code) you should use construct like this one:

render(template:"/templates/common/messageBoxTemplate", model:[title:"hello world"])

If you are rendering template from gsp page you should use construct like this one (actually taken from grails documentation):

<g:render template="displaybook" model="['book':book,'author':author]" />

To be honest I try to avoid using <g:render... from gsp pages because if you are using tags it is easier to read the gsp page. Another advantage of using tags is that it is easier to refactor the gsp pages. So when you find yourself writing <g:render template.... in the gsp page, introduce grails tag for that.

Tags

The advantage of tags is that they have access to the GORM classes and you can inject any grails service into tag. So if you need to perform some calculation that needs to be displayed on the gsp page tag is the right place for that.

Another way to send data into grails is via attrs map. Each tag is specified in the file ending with TagLib and the format of the tag is:

def messageBox = {attrs, body ->
out << render(template:"/templates/common/messageBoxTemplate", model:[title:attrs.title, body:body()])
}

So tag is closure with two variables: attrs and body. Using attrs you can access any custom data sent to the tag.

So how do we send that data?

When displaying tag from the gsp page you are using construct like this one:

<g:messageBox title="Register, it takes only seconds">

In this case the title is custom data sent to the tag.

To execute given tag from the controller or some other groovy code you can use construct like this one:

g.messageBox(title:"Register, it takes only seconds") {
//body to be displayed
}

So for example, to display number of registered users on the grails and groovy tutorials page I am using direct access to database from the tag and then sending those data to the model. But I could also create e.g. application scoped variable for this and gain some performance. So currently the code in the tag looks like this:

def dataInfo = {attrs, body ->
def postsCount = TutorialLink.count()
def userCount = User.count()
out << render(template:"/templates/common/statsTemplate", model:[userCount:userCount, postsCount:postsCount])
}

Monday, August 17, 2009

Agile, TDD and upfront desing

As TDD and agile software development are emerging as more and more used technologies for software development lot of software developers are jumping into it without having real knowledge.

From my point of view one of the misconceptions about TDD and agile is that you don't need any design and architecture upfront. TDD with refactoring will give me the right architecture in all cases.

Although I am big fun of agile software development I don't believe this is idea of the agile. Agile is here to help develop better software for better customer satisfaction. But it in no cases claims that you should forget about big picture, about documentation and about having at least basic understanding of your system design.

From my point of view you need to do basic design at least at the high level. Then for important parts you need to go to lower levels (if really necessary). And then agile together with TDD will help you to really get it right. To separate concerns, to make separation between domain objects in different tiers and so on.

So as conclusion, agile does not mean no more thinking. Agile means think about the problem, do basic planning and then use TDD and other agile tools to get it right.

Monday, August 10, 2009

g:form, g:actionSubmit and Internet Explorer 8

While working on my latest grails powered web site things to do with kids I have noticed that one form performs ok in Firefox and Chrome but not in Internet Explorer. If this would be case with grails tutorials I wouldn't care too much because majority of visitors have Firefox or Chrome. But my statistics for things to do with kids are showing that there is more visitors using IE than other browsers.

The problem was following. E.g. on the home page of things to do with kids you enter the city name and then press enter on your keyboard. In Firefox and Chrome you get the list of places to visit but in IE8 nothing happened.

But if you used tab to move focus on the Show Me button then everything worked also in IE.

The initial code looked like this:

<g:form controller="home" method="GET">
<input name="locationName" class="span-10 last" />
<g:actionSubmit value="Show me" action="placesAroundLocation" />
</g:form>

After some investigation I noticed that closure called from IE was actually index in the HomeController. So this means that in IE8 when enter is pressed while focus is in the input box default action of the controller is called while in Firefox and Chrome action of the button was called.

So to fix the problem with the IE I have slightly change the code. I added form default action so now it looks like this:

<g:form controller="home" action="placesAroundLocation" method="GET">
<input name="locationName" class="span-10 last" />
<g:actionSubmit value="Show me" action="placesAroundLocation" />
</g:form>

I didn't check behavior in other versions of IE but if you have similar problem this may help you.

Tuesday, July 28, 2009

You don't need session in Grails service

From time to time there are questions or blog posts that explain how to obtain access to web session from the grails service or domain class. If you really need to access session from the service class e.g. this post from Robert can help you.

But before you start reusing session in your services or even domain classes be careful and think if you really want that. Service should be more or less simple Java class and when ever possible should not depend on special environment classes. And session is actually very special web application environment class.

So what to do if in the service you really need that value from the session? Well the answer is of course very simple. Send it as a method parameter. Or another way is Robert's approach to create service that will return that value from session and inject it into service that really needs that value.

This way your services will not depend on the web container context and you can easily port them to other environment.

Tuesday, July 21, 2009

UK included on spend day with kids

As you may know few weeks ago I have launched spend day with kids web site. In the first release only USA was covered but yesterday I have finished entering attractions for UK.

So please feel invited to visit spenddaywithkids.com and search for ideal places to have a day full of fun with your kids.

Friday, July 17, 2009

Groovy and Grails help build apps faster

Actually this is not my post but a very interesting article about productivity gained using Grails and Groovy.

Usually I am not posting links to other articles but my feeling is that this one deserves this. I didn't notice link to this articles on other grails/groovy related sites so I want to share it.

So navigate to "Groovy and Grails help build apps faster" to read the whole case.

Sunday, July 5, 2009

Spend day with kids Grails web app launched

I have launched new Grails powered web site www.spenddaywithkids.com.

Idea of the web site is to help you find interesting places where you can go with kids. There are places like zoos, water parks, theme parks....

Developing this application was interesting for me because this was for me the first time I used google maps in some of my application. Also new for me was geocoding but actually this turned out to be as easy as reuse formulas available online. Currently on USA is covered but Europe should come soon.

Currently I have three sites online: grails tutorials, software books reviews and spend day with kids.
For me it is just prove that development of web applications with Grails is easy and fun but know I will concentrate on extending my existing site and hope I will not get any fun idea soon :)

Let me know if you have some proposals for any of mentioned sites.