Web Application Development Practical: Ruby on Rails - Working with Database (II)This practical deals with multiple tables in a web application. Before doing this practical, you should have finished the previous practical. Before we start this practical, 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 ViewsFirstly, we improve the web page that shows the list of all recipes. We take over the handling of the list action from the scaffolding. Edit recipes_controller.rb (under cookbook/app/controllers) and add a list method similar to Figure 1. def list
You have to enable in your routes file any extra methods you add to the controller as well: Edit routes.rb (under cookbook/config) like Figure 2, by adding the following: resources :recipes do
Figure 2. Add new method to routes file
<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 recipes_controller.rb and add the single line of code to the list method. def list
When a user browses to http://127.0.0.1:3000/recipes/list, Rails will call the list method we just created. The single line of code in the method asks the Recipe class for all recipes from the database, assigning all the recipes to the 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| %> 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 CookbookWe want to be able to assign a recipe to a category (like "Food") and be able to list only those recipes that are in a particular category. To do this, enter this command in your terminal (make sure you are in the cookbook directory):
Then, use a rake command to run the migration:
Browse to http://127.0.0.1:3000/categories/new and create two categories named Food and Beverage.
Assigning a Category to Each RecipeThe cookbook application now has recipes and categories, but we still need to tie them together. We want to be able to assign a category to a recipe. To do this we need to add a column to our recipes table to hold the category id for each recipe, and we'll have to write an edit action for recipes that provides a drop-down list of categories.
In the sandbox mode, all operations we did to the database will be rolled back. When we enter the console, type the following command:
The above command will return the first record in the recipes table, take a look at the returned record and check whether it contains the field category_id. Type “exit” to quit the console mode. Notice if there is anything wrong in the migration, we can always roll back the last migration by using:
After the category_id has been added to the recipes
table, now tell the Recipe model class about this too.
class Recipe < ActiveRecord::Base
class Category < ActiveRecord::Base
def edit
The following block is inserted:
<div class="field"> You can see the @recipe and @categories variables being used. You may found this discussion about the method collection_select useful. The method collection_select can automatically load all values of @categories, and it can also pre-select the value of category according to the current recipe. Study this template and then try it out. Browse to http://127.0.0.1:3000/recipes/list and edit the recipe for "Tap water for everyone" Change its category to "Beverage," as shown in Figure 9.
Continue to modify the rest of the application to make it consistent with the newly added field. For example, 1. you should show the category option when you create a new recipe or show the details of a recipe. 2. You could add a function that can list all recipes given a category name or ID (consider using @category.recipe to list all recipes having the same category) ExerciseContinued from the previous exercise, you are required to create a category table for your to-do list application. And this table should contain at least three entries such as business, personal and family. Then link the category table with the to-do list table from the previous exercise and assign a category to every entry in the to-do list table.
|