Grails, a crash course.

The following sections are in no particular order.

Grails

This document covers the Grails 0.4.x release.

Grails can be found at http://grails.codehaus.org. While most of this will be applicable to the 0.5 release there are probably some items in here that will become obsolete.

Before we get started...

Grails is not Rails. It's not even close. Grails is where I think Rails was about a month after it's creators finished getting ActiveRecord put together. It's functional, but immature. Despite it's hype this is not something you should even think about touching unless you're ok with living on the bleeding edge. Things are changing in the development trunk in dramatic ways. They're still putting the doors on the car so "polish" is something that isn't really a consideration yet.

This was originally written as a personal reference document. It's haphazard, in no particular order, and should not be considered an introductory guide. However, it is useful as a quick reference document. If you find a problem with it please drop me an e-mail at masukomi at masukomi dot org.

Reference Links

Eclipse Integration

Grails has Excellent Eclipse integration. You have to set up the GRAILS_HOME variable and a couple other little things but it will build .project and .classpath files and a run configuration for you. There's a page with all the details here.

Setting up your database

Because Grails can work in test, develpoment, and production modes it will let you, if you want, configure a different database for each one. That way unit tests won't blow away production data. Yay. In your grails-app/conf/ directory you will see three ____DataSource.groovy files. Editing them should be self explanatory. Note that if you're using Eclipse this directory will be listed amongst your source directories. Obviously, make sure you have the appropriate jdbc driver jar in your lib directory. 

By default Grails is set up to use HSQLDB, which is an in memory database that works well for development, although it doesn't seem to be configured to persist anything between runs.

Basic Domain Model operations

.get(id)

Takes the id of the object you'd like to load as a parameter. 

def myFirstBookmark = Bookmark.get(1);

.save(), .delete()

If you can't figure out what these do you need to go home now.

Getters and setters

In Grails there is no need for getters and setters. Just use the name of the property you want to work with. If you want to set it to something new then say:

myFirstBookmark.url = new URL('http://grails.org/Home');

If you want to see what the url is you just say:

def myFirstUrl = myFirstBookmark.url;

Dynamic Querying

.find(...) and .findAll(...)

These both take an HQL (the Hibernate Query Language) string as their parameter and the first result or all of the results respectively.

def grailsBookmark = Bookmark.find('from Bookmark as b where b.title = ?', ['Grails'])

Alternately these can be used for finding by example. Just pass in a new Domain object with the properties you are looking for.

def bookmark = Bookmark.find( new Bookmark(title:'Grails') )

.findBy* methods

DomainModel.findBy<attribute_name>[<And/Or><another_property_name>]<expression>(<first_property_value>[, <further_property_values>])

For example: Bookmark.findByTitleAndUrl('Grails', new URL('http://grails.org') )  
or Bookmark.FindByTitle('Grails')

Expression is the tricky bit. It can be any of: 

Between, obviously, takes 2 arguments. But combining it with multiple properties separated by And or Or would be confusing at best, and I don't think it would work anyway.

.findAll(...)

The findAll(...) method supports querying via HQL.

def allBookmarks = Bookmark.findAll('from Bookmark')
def grailsBookmark = Bookmark.find('from Bookmark as b where b.title = ?', ['Grails'])

.executeQuery(...)

Like findAll executeQuery takes an HQL string as it's parameter:

def tags = Bookmark.executeQuery('select elements(b.tags) from Bookmark as b')

Note that in this example tags is actually a related domain object. Hibernate being the glorious goodness that it is takes care of this for you.

.findAllBy* and .countBy*

.findAllBy* is essentially .findBy* except it returns a list. .countBy* is also essentially .findBy* except it tells you how many matching instances there are.

Finding by criteria

def c = Bookmark.createCriteria()
def results = c.list {
        like('title', 'Grails%')
        between('dateCreated', new Date()-10, new Date())
}

The nested method calls within the closure block translate into method calls on Hibernate’s org.hibernate.criterion.Restrictionsclass, which is obviously too much to go into here. However there's some nice examples of using the Hibernat Criteria Builder in the context of a Grails closure here.

There's more on the normal list method below.

Listing, Sorting, and Counting:

.list(...)

The list method can accept a hash as it's optional parameter. It understands four keys:
• max: The maximum number of instances to return
• offset: The offset relative to 0 of the first result to return
• sort: The property name to sort by
• order: The order of the results, either asc or desc for ascending and descending order
  respectively

.list(...) never returns null. Instead it will pass back a list with a .size() == 0

// get all the bookmarks, careful there might be many!
def allBookmarks = Bookmark.list()
// get the ten most recently created bookmarks
def topTen = Bookmark.list(max:10,sort:'dateCreated')
// get the last ten in descending order of creation
def lastTen = Bookmark.list(offset:Bookmark.count()-10,
                                       sort:'dateCreated', order:'desc')


.listOrderBy<parameter_name>()

Returns a list ordered by the parameter name you tack on to the end of it.

Unit Testing

Getting the unit tests hooked into Eclipses graphical jUnit test system isn't worth the effort. Hopefully this situation will change in the near future. For now, just run all your tests from the command line.

In addition to the default assertions provided by jUnit's TestCase class Groovy adds in the following:
Once you've written your tests simply run the following from the command line.
grails test-app
It will, of course, use the test database for testing.

Functional Testing

Grails uses Canoo WebTest for it's functional tests. The grails create-webtest has been rolled into grails generate-webtest in 0.4. To create a test for a controller just grails generate-webtest <ControllerName> then drop into the webtest/tests directory and start hacking the newly created file. You'll need the manual with all the WebTest methods you'll want to access. You want the bits under Core Steps and Extension Steps.

To run your test grails run-webtest  but make sure you don't have a grails run-app process already going or it will not be able to grab the port.

Logging

Every Grails controller includes a logging mechanism already; so now there is no excuse to not log information appropriately. The log property is an instance of
org.apache.commons.logging.Log

Configuration is handled in grails-app/conf/log4j.<environment>.properties

To log something in a controller you just say something like:
log.debug('I am important debug information');
The log4J docs have more information on the myriad possibile configurations and method calls it provides.

Gotchas

Don't write getters that don't correspond to DomainClass properties. 

Don't do it in an interface and don't do it in a Domain class. Grails and Hibernate try to do their magic on them but they don't map to anything so it blows up. Setters are ok. Just think of creative way to reword it. Instead of User.getEmployer() try User.myEmployer() or just User.employer().

If you specify a return type on a method make sure it's not an interface. If you're need to return one just don't specify the return type at all.

Don't write finders (ex Foo.findBar()) 

Grails creates dynamic finders. If you make your own they won't work.

Namespacing is borked in many places. 

Don't create unit tests that aren't in the default package. While it may compile just fine in Eclipse running grails test-app will blow up. Use the default package. Yes, this sucks.

Annotations 

If you're referencing the Grails subversion repository to figure out how things work you'll notice a lot of annotations being used that aren't mentioned in any of the docs. You need to hook in annotations in the xxxDataSource.groovy and you have to use .java files for your annotated beans not .groovy files.

index.jsp

Not so much a "gotcha" as a non-obvious piece of information. Grails doesn't have a formal routing system like Rails does. So, your site's home page is the web-app/index.jsp file. If you want to redirect to a controller or put up happy pretty things for the home page then that's where you need to do it. 

setters

If you write a setter that does correspond to a property of your domain class it will be ignored. You have to give it a name other than set<CapitalizedPropertyName>.

Tips

Grails does a lot of behind the scenes magic. Do not assume things are going to work the way you expect when you're first starting out. Instead depend on the test suites to confirm your suspicions. Constantly go back and forth between writing features and testing them, in very small increments. Don't fill out the guts of 3 classes or an entire controller and then see if it works. Instead write a method and tests it, then move on to the next one. Trust me, this will save you much hair pulling. Not only is it going to catch issues where Grails doesn't work the way you think it does but it will also catch simple runtime errors that the Eclipse Groovy plugin will allow to compile just fine.

Domain Class Relationships

Defining Object Relationships with GORM covers the basics, but it leaves a bit to be desired. Things like info on the relatesToMany property: 
Foo { static relatesToMany = [bars : Bar]; }   
This seems to work like hasMany. I haven't a clue what the difference is, maybe it ties things together but doesn't imply ownership, and thus no cascading saves?

Commonly used commands

Views & Layouts

Grails uses SiteMesh to manage it's layouts. There is also a lot of managing of views and layouts via convention. It's all pretty simple and there is a good overview of how it all fits together on the Groovy Views & Layouts page. The non-obvious bit that should be pointed out is that when you're making a piece of HTML that you know will be shoved into a layout most people would assume that you would only create that portion of the HTML. Not so in grails. You create the html, head, and body tags, add a magic meta tag into the head that SiteMesh leverages and the portion that will be inserted into the layout is whatever you've put between your body tags. This means you should be able to preview your code snippets better and I'm sure there is other non-obvious nifty magic that SiteMesh will leverage if you read it's docs and learn the incantations. 

Shared templates are supported with the same core rules as those defined on RoR
<g:render template="/test" model="[:]" />

Results in evaluating a template called
grails-app/views/_test.gsp

You'll find the GSP tag reference useful.

CSS and JavaScript files live under the web-app/css and web-app/js directories.

i18n

Grails utilizes Spring to figure out what language file to utilize. The language files are grails-app/i18n  the default file is grails-app/i18n/messages.properties if you want to add another language like spanish, just add a new grails-app/i18n/messages_es.properties where es is the two letter language code. 

To utilize them in your views just use this tag <g:message code="property_key_here" /> 

There's no way to utilize these messages in your controllers for flash.message type responses unless you want to hook into it through whatever Spring mechanism is loading them. The current suggestion is to instead just return the message key and handle displaying them correctly in the view with a standard message tag: <g:message code="${flash.message}" />

The message tag takes 4 parameters. They're all optional but you won't get too far without code or default.

  1. Args is useful because you can put {n} tags in your message.property file values where n is the index into the incoming args list. Also, note the lack of a $. 

Controllers

The docs, and examples cover controllers pretty well. One non-obvious feature is that when setting properties on an object from params like this:
def foo = new Foo();
foo.properties = params;

You can also use dot notation to set the properties on it's related objects (so long as they aren't lists). So if your Foo belonged to or had one Bar and it had a "name" property you could pass in a parameter with the key of "foo.bar.name"
foo.properties = params; // now sets foo.bar.name too

This goodness comes via Spring and, i'm betting, ognl.