Article
Get On Track with Ruby on Rails
Page: 1 2
Running on Rails
Keen to see the scaffolding in action? Me too! In your terminal window, move into SL and type:
> ./script/server webrick
This instructs Rails to launch WEBrick (a lightweight Ruby web server) and boot up our ShoppingList application (squeal!):

Our application is now running! It's available on your box at:
<http://localhost:3000/>
Don't believe me? Go ahead and try it out now. You'll see a default welcome page, which we're going to change later.
CRUD: C is Create
Let's check out this so-called CRUD, shall we? Don't get ready to wash your hands of it just yet! Visit:
<http://localhost:3000/list_items/>
You'll be presented with a page like this:

Click that New list_item link. The following form was generated for you by Rails, based on the table we created earlier. Cool, huh? Fill the form out! Add something to your shopping list! I'll do it too.

See that? It's that easy to Create something.
CRUD: R is for Retrieve
The object you just created now lives inside SQLite, and we didn't even have to lift a cruddy finger! Want proof? Get back into the SQLite console, and type in:
> select * from list_items
Our little database has been magically populated!
You'll see a bunch of links alongside our newly created item -- Show, Edit and Destroy. Go on, click Show: You know you want to!

Rails is pulling the information from our database and displaying it for us -- now that's what I call Retrieval!
CRUD: U is for Update
Now, click the Edit link at the bottom of the page there, and change around some of the values in your item:

Click Update once you're done, and yes, just as you expected, voilá! Instant database updating at work!
Getting excited by the possibilities? You should be!
CRUD: D is for Delete, Destroy, Deprive of Life, Destination: Deadsville
Now we come to the hardest part of all -- letting go. We're going to pull the plug on our list item without so much as a second thought. No, no, don't cry! It's for the best, really. How else can I demonstrate Delete?
Fight back your tears and click the Destroy link on the main list_items page. Because Rails is so polite, you'll be prompted to confirm your choice first. Go on, do it. Trust me, it will be worth it.

BOOYA! Just like that, your item is wiped from the face of the Earth. Go back and run the select * from list_items query in SQLite, if you want proof.
Moving Along the Rails
So you have some idea of what CRUD is, and how it works via your browser. But what about the actual code that makes it go? Let's take our relationship one step further by building our own scaffolding and Views, rather than have Rails generate these for us! In the main SL folder, type:
> ./script/generate scaffold ListItem
When asked, hit "Y" (Yes) to overwrite our existing files:

We've just asked the generate script to flesh out our Controller with the methods that are needed to perform CRUD operations, and the Views to display those methods in action. If you open up the list_items_controller.rb once again, you'll see that it's been stuffed full of chewy Ruby goodness. There are now eight new methods in our Controller:
- index
- list
- show
- new
- create
- edit
- update
- destroy
Let's take a quick peek at each of those:
index
The method is simply making a call to the list method, and requesting that the list View be rendered.
All Views in Rails are "rendered" (displayed, usually in a web browser) either explicitly, as is the case here, or automatically. If you don't specify a method to render, and your method isn't redirecting to another URL, Rails will try to find a file that has the same name as the current method. It looks for a file that ends in rhtml or rxml, in the app/views folder named after the Controller.
So, if the index method wasn't rendering the list View, Rails would look for a file called index.rhtml or index.rxml inside app/views/list_items/.
list
Here's a weird-looking method! We're calling the paginate method, which takes the name of a Model and a bunch of optional settings, and splits the results so that you can easily view long lists across multiple pages. In this case, we're asking the method to split up all of our list_items into pages with a maxiumum of ten items per page. Notice that the result of the method call is being passed to not one, but two variables?
This is because the paginate methods returns an Array object -- one of many built-in objects in Ruby -- and Ruby lets us assign the result inline. Thus, our first instance variable (@list_item_pages) is assigned the value of the first item from the resulting Array, and our @list_items variable is assigned the second item.
Handy!
We're not using a 'return' keyworld, because in Ruby, they're optional -- Ruby will just return the last statement in a method by default. You'll also see that we're not requesting a View to render. Remember, Rails is going to look for a list.rhtml or list.rxml file, as noted above.
show
Now we get to play with ActiveRecord and our ListItem Model. One of ActiveRecord's many methods is find.
Pass it an ID or a bunch of SQL conditions, and it will split back either a single ListItem (if only one is found) or an Array of ListItem (if a whole bunch of them match your criteria). Here, we're asking it check for a particular ID passed in via the params Hash.
A Hash in Ruby is like a Dictionary in other languages. You set a value for a particular key, each key needing to be unique. Here, the params Hash is filled out by Rails' dispatcher whenever a request comes in. If we were to view /list_items/show/1, by default, params would contain useful information like:
action: show
id: "1"
controller: list_items
Again, no View is specified, so Rails will use the show.rhtml file that lives inside app/views/list_items/.
new
This one is fairly simple -- it creates a new ListItem object and returns it. However, it does not exist in the database. Until you save or update an ActiveRecord object, it's nothing but a puff of logic floating around the ether.
create
Any guesses on this one? Creating an object, you say? Correct -- have a cookie. If you're thinking that's what new is for, you're right: it is. And, like the new method, where we create an object with ListItem new, we create an object here by passing in values sent via our new friends, the params hash. This pre-fills the object with any values that match those belonging to our class. If you were to take a peek inside params when we call this method, you'd see something similar to the following:
name: Giant slab of Tofu
cost: 25
quantity: 10
You know our Model has this, since you and I built it together.
Here you can see that, this time around, we're actually calling the save method, which does commit our new object into the database. If we're successful, we' make a note of it into the flash value, and redirect to an action.
Flash?! Relax, I'm not talking about .SWF files. A "flash" in Rails is a way of displaying a one-shot message to the viewer. In this case, we're letting them know whether or not the save worked. If it did, we tell Rails to redirect to our list method, which calls it just as if we'd done so ourselves.
And if it didn't, because the database suddenly ate itself or a glitch in the Matrix set your hard drive to randomly nuke a few sectors, then we're just going to render the new action and pretend that we took the blue pill and nothing ever happened.
edit
While essentially they're the same, the edit and show methods render different views, which means that you end up with very different results, even with the same code.
update
This one is almost identical to the save method, except that it calls the update_attributes method in place of save to update an existing item in our database with new values (or create a new one if the particular item doesn't actually exist -- Rails is smart like that).
destroy
Kill, kill, kill. Find the requested item, remove it from the database, and redirect back to the list View.
Enough said, really.
Views
So, how about these Views I keep mentioning? Well, I was just getting to that. Rails works around the concept of Layouts, Partials and assorted sundries to make up the V in MVC. Think of a Layout as a skeleton into which you inject the meat of your application -- if you're familiar with the concept of a header and footer template that you wrap around your generated content, you're on the right track.
Open up the list_items.rhtml file inside app/views/layouts/:
<html>
<head>
<title>ListItems: <%= controller.action_name %></title>
<%= stylesheet_link_tag 'scaffold' %>
</head>
<body>
<p style="color: green"><%= flash[:notice] %></p>
<%= @content_for_layout %>
</body>
</html>
Looks like normal HTML with a few weird extras, right? That's exactly what it is! The <%= %> stuff is what's called ERB -- Embedded Ruby. If you've used PHP at all, you'll feel right at home.
ERB lets you stick chunks of Ruby code anywhere you like inside your .rhtml (Ruby HTML) files. There are two types of ERB tags we need be concerned with:
<%= ... %>- The result of any code put between these tags (note the equals sign) will be output to the page.<% ... %>- What happens inside these tags stays inside these tags.
Thus, the line <%= controller.action_name %> is going to spit out the name of the current action the Controller is processing. If you'd put it inside <% %> tags, nothing would appear. Note the <%= flash[:notice] %> call? Ahhh, you say nodding your head. Now it's all falling into place!
And the meat in this markup skeleton? <%= @content_for_layout %> fills in the blanks, attaching whatever we've requested to be rendered.
Now what?
Why wouldn't you just use the default scaffolding in Rails, instead of having your own methods and View files?
Because scaffolding is only one small part of the Rails framework -- a powerful one, yes, but relatively minor nonetheless. There's a lot left for you to explore yet!
And since you now have your own .rhtml files, you're free to go and put your personal touches into this application. However, given the length of this article, I'm going to spare you of any more embarrassing anecdotes and leave you to take the reigns. By now you should have enough of an idea to sit down, pour over the Rails API documentation, and start out on your own little web applications.
Thanks for playing! You've been a great audience.