Rolling with Ruby on Rails
Pages: 1, 2, 3, 4, 5

What Just Happened?

A single line of code, scaffold :recipe, brought everything to life. It let us begin working with our data model. With virtually no work on our part, it created the actions list, show, edit, and delete. It also created default view templates for each of these actions.

Of course, these actions and views are very plain--not the sort of thing you'd want users to see (unless they are total geeks). The good news is that we can leave the scaffolding in place and slowly, one at a time, provide our own versions of the actions and views. Each time you create one of the actions or views it will override the scaffold's version. When you're done, simply remove the scaffold statement from the controller.

Before we do that, did you notice the URLs as you were playing around with your new cookbook? Rails tries very hard to present the user with pretty URLs. Rails URLs are simple and straightforward, not long and cryptic.

Creating Actions and Views

The page that shows the list of all recipes desperately needs improvement. The way to do that is to take over the handling of the list action from the scaffolding.

Edit recipe_controller.rb and add a list method similar to Figure 40.

A new list method
Figure 40. A new list method

Browse to http://127.0.0.1:3000/recipe/list and you should see something like Figure 41.

the results of the new list method
Figure 41. The results of the new list method

Because we just created our own definition for the list action, Rails no longer uses the scaffold version. Rails called our list method and then tried to find a view template to render. Because we did not create one, we received this "template missing" error. Let's create our own view template for the list action that only shows each recipe's title and date.

When we created our recipe controller, the generate controller script also created a view directory where we can place the HTML templates that the recipe controller can display. We need to create a template file named list.rhtml in c:\rails\cookbook\app\views\recipe. If you have worked with JSP or ASP pages, this will look familiar. It is simply an html file with Ruby code embedded within <% %> and <%= %> tags.

In the directory c:\rails\cookbook\app\views\recipe, create a file named list.rhtml containing the following:

<html>
<head>
<title>All Recipes</title>
</head>
<body>

<h1>Online Cookbook - All Recipes</h1>
<table border="1">
 <tr>
  <td width="80%"><p align="center"><i><b>Recipe</b></i></td>
  <td width="20%"><p align="center"><i><b>Date</b></i></td>
 </tr>

 <% @recipes.each do |recipe| %>
  <tr>
   <td><%= link_to recipe.title, :action => "show", :id => recipe.id %></td>
   <td><%= recipe.date %></td>
  </tr>
 <% end %>
</table>
<p><%= link_to "Create new recipe", :action => "new" %></p>

</body>
</html>

Edit recipe_controller.rb and add the single line of code shown in Figure 42 to the list method.

listing all recipes
Figure 42. Listing all recipes

Refresh your browser and you should see something like Figure 43.

a nicer recipe list
Figure 43. A nicer recipe list

Now this definitely looks better! How does it work?

def list
  @recipes = Recipe.find_all
end

When a user browses to http://127.0.0.1:3000/recipe/list, Rails will call the new list method we just created. The single line of code in the method asks the Recipe class for a collection of all recipes from the database, assigning the collection to the instance variable @recipes.

Next, Rails will look for a template to render and return to the browser. Most of our list template is standard HTML. The real action is in this section of the template:

<% @recipes.each do |recipe| %>
  <tr>
   <td><%= link_to recipe.title, :action => "show", :id => recipe.id %></td>
   <td><%= recipe.date %></td>
  </tr>
 <% end %>

This embedded Ruby code iterates through the collection of recipes retrieved in the controller. The first cell of the table row creates a link to the recipe's show page. Notice the attributes used on the recipe object (title, id, and date). These came directly from the column names in the recipes table.

Adding Categories to the Cookbook

We want to be able to assign a recipe to a category (like "dessert") and be able to list only those recipes that are in a particular category. To do this, we need to add a category table to the database, and a field to the recipe table specifying the category to which the recipe belongs.

In MySQL-Front, create a categories table. Remember to change the automatically created Id field to id, and then create a name field as a varchar(50). The resulting table should look like Figure 44.

the categories table
Figure 44. The categories table

We also need a category controller and a category model. Open a command window in the cookbook directory and run the commands (Figure 45):

ruby script\generate controller Category
ruby script\generate model Category

creating the category model and controller
Figure 45. Creating the category model and controller

Finally, add scaffolding to the category controller. Edit c:\rails\cookbook\app\controllers\category_controller.rb and add the scaffolding shown in Figure 46.

category scaffolding
Figure 46. Category scaffolding

Browse to http://127.0.0.1:3000/category/new and create two categories named Snacks and Beverages. When you are done, you should see something like Figure 47.

a listing of all categories
Figure 47. A listing of all categories

Pages: 1, 2, 3, 4, 5

Next Pagearrow