For an upcoming job, I need to learn Grails. Groovy on Rails is one of the newer frameworks to come out, so it was a little troublesome to find a good guide to starting. I found the user guide but was instantly turned off by the HUGE amount of knowledge suddenly thrown at me. Being a normal human being, I instantly turned to finding some simple tutorials to help me out.
After watching the 3 screen casts and troubleshooting an error of my own that wasn't covered (modifying the bootstrap file to add a correct instance of a Task), I decided that I had enough information to try to throw together a tutorial of my own (blind leading the blind!).
Without further a due, here we go:
First off I navigated to where I wanted the project to be and ran the grails create-app Inventory command to create my project
Next, I create a Domain class so that I'll have the ability to connect classes together through relationships in the database, as well as it's controller so that I'll have something "nice" to look at when I try to navigate to the controller in my url. Below are screenshots of the sequence of commands, as well as the "nice" thing to look at. You can see that I restarted my app after making the controller. I did this without CTRL-C'ing the application by creating an empty file called .kill-run-app in the top level of my grails project. This is a shortcut to stopping a server that I found here.
The commands I executed to create the domain class, it's controller and to run the app are here:
create-domain-class Item
run-app
create-controller Item
run-app (after killing it with the .kill-run-app trick)
What the initial controller looks like (error explained in a moment) |
The commands to create domain class and controller |
Now run the following commands in the grails console:
create-domain-class Type
create-controller Type
Creating another domain class and controller |
The running app can see it's controllers. Navigating to these will give you the error page from before |
Tada! Now let's actually start coding. What we want to do is add some property fields to the two domain class's so they'll actually be useful, and then we'll want to assure ourselves that everything is working nicely. Blogger doesn't have a good source code format so I'll just be throwing in screenshots of my text editor.
The files we'll modify are:
grails-app/domain/inventory/Item.groovy
grails-app/domain/inventory/Type.groovy
grails-app/controllers/inventory/Item.groovy
grails-app/controllers/inventory/Type.groovy
In the two domain class files, we'll add in the properties and define some constraints on the system. For each Item we'll need a name, a description of what the item is, where the item is and how many of the item we have. The constraints on Item's will be that their name and location can't be blank, that there must be at least 0 of them, and the name of the Item is unique. Type's are pretty simple, they need a unique non-blank name and that's it. Between the two we define their relationship as Many-To-Many using the static hasMany and static belongsTo properties. It's fairly intuitive to see how groovy expresses that we have many types of a class called Type in that one hasMany statement. In order for the relationship to function, one side of the relation has to belong to another, in this case, the Type belongs to the Item, which means that we add the static belongsTo=Item line into the Type domain class.
Within the controllers we remove the automatically defined index function, and simply add the line:
static scaffold = Type inside the type controller, and static scaffold = Item inside the Item Controller. This sets us up with a CRUD(Create, Read, Update, Delete) view.
The source code so far |
A simple CRUD interface by specifying scaffold to the type, or to true |
Simple so far right? The nice thing about using a framework is that SO much get's done for you with a few simple lines. So at this stage we have our objects and their relationships, and now we just need to display them and provide an interface to the user.
To do this, we're going to modify the default index.gsp file since it's got some nice styling that we can use right off the bat. First off we'll want to remove the Grails image form the top right. To do that we'll edit the file grails-app/views/layouts/main.gsp
Changing the layout file |
I've hacked it a bit, simply removing the src of the image and forcing the image to be invisible with some (evil) inline css. This is the fastest way to keep the nice green boarder grails provides us with, and do away with their image all at once. If you simply remove the img tag, then the green bar at the top will collapse down to 0 height and that's no good.
Next we edit grails-app/views/index.gsp to be pretty much blank so that we can have at it. I've taken out most of the html content, changed the title tag in the head, and left a snippet of code we'll be modifying to display out items.
Modifying the index page |
Unfornately, how to throw interesting data onto your index page is not immediately apparent in Grails since it's using what looks like static information to me. SO, with some help from stackoverflow, we can edit the grails-app/conf/UrlMappings.groovy file to send the index page along to a controller. So we need to make that controller! Running create-controller Index will do the trick just fine. Then we can copy the default index.gsp file to the grails-app/views/index/index.gsp file and then our new Url Mappings will work just fine!
Create the new controller. Whenever you want a new page, you pretty much make a new controller |
Now we need to pull information from both the Types and the Item's controllers. To do that we'll hop into the IndexController located in grails-app/controllers/inventory/ and add some values for us to send along. See the screenshot of the controllers code on the right, and the changes to the index.gsp file to make things appear.
Houston, we have liftoff |
And the code doing the work, we haven't used the types yet, but we will! |
Add the toString function to type and modify the index file to output it |
The result of the toString and output |
Add links to allow users to edit |
The User interface now |