何が起こっていたのか?
一行のscaffold :recipe
がすべてを実現した。その一行がぼくらのデータモデルを実際に動くようにした。ほとんどぼくらには何も作業をさせずに、この一行はlist
,
show
, edit
, そしてdelete
の機能を作成した。そして、それぞれの機能のデフォルトビューのテンプレートも作成した。
もちろん、その機能やビューはとても単純なものだ。あなたがユーザーに見てもらいたいようなたぐいのものじゃない(ユーザーが皆、ギークなんじゃないかぎり)。でも、嬉しいニュースがある。ぼくらは足場(scaffolding)を残したままで、時間をかけて一つ一つに独自のアクションとビューを提供することができる。あなたがアクションやビューを新しく作成するたびに、それらはscaffoldバージョンの定義をオーバーライドする。あなたがすべての作業を終えたら、単にあなたのコントローラークラスからscaffold
文を削除するだけでいい。
さてそれをする前に、あなたの新しいcookbookで使っているURLには気をとめただろうか?Railsでは、ユーザーに少しでも見やすいURLを見せるようにしている。RailsのURLはシンプルでわかりやすい。けして長く難解なものではない。
アクションとビューを定義する
すべてのレシピを一覧表示しているページは、かなり改良する必要がある。どうやればいいかというと、Scaffoldされているlist
を上書きしてやればいい。
recipe_controller.rb を編集して、list
メソッドをFigure 40のように追加してほしい。
Figure 40. 新しいlist
メソッド
http://127.0.0.1:3000/recipe/list
を見てみると、Figure
41のように見えると思う。
Figure 41. 新しいlist
メソッドの表示結果
ぼくたちが独自のlist
の動作を定義したので、Railsはもうscaffoldされたものを使わなくなった。Railsはぼくらのlist
メソッドを呼び出し、レンダリングするためにビューのテンプレートを見つけ出そうとした。でも、ぼくらはテンプレートを作成していなかったので、この"テンプレートが見つかりません"(template
missing) エラーを受け取ることになったのだ。
それじゃあ、list
に独自のビューテンプレートを作成することにしよう。これは、レシピのタイトルと日付だけを表示するものにしよう。
ぼくらがレシピコントローラーを作成したとき、generate controller
スクリプトは、レシピコントローラーが表示するHTMLテンプレートを入れておくためのviewディレクトリも作成していた。list.rhtml
という名のテンプレートファイルをc:\rails\cookbook\app\views\recipe の中に作成しなければならない。あなたがJSPやASPのページを作ったことがあるようなら、これは同じように見えるだろう。このテンプレートファイルは、単純なHTMLファイルで、Rubyのコードが<%
%>
と<%= %>
のタグで埋め込まれている。
c:\rails\cookbook\app\views\recipe の中に、次のような内容のlist.rhtml という名前でファイルを作成しよう。
<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>
recipe_controller.rb を編集し、Figure 42のようなコードを一行list
メソッドへ追加する。
Figure 42. 全てのレシピを表示する
ブラウザを更新すると、Figure 43のように見えるだろう。
Figure 43. ちょっとよくなったレシピリスト
これで、確実に見た目がよくなった。どうやって動いているんだろう?
def list
@recipes = Recipe.find_all
end
ユーザーがブラウザでhttp://127.0.0.1:3000/recipe/list
を見ると、Railsはぼくらが作ったばかりの新しいlist
メソッドを呼び出す。メソッド内の一行のコードがRecipe
クラスにデータベースからすべてのレシピのコレクションを返すように要求を出す。そしてその結果をインスタンス変数@recipes
へ入れる。
次に、Railsがレンダリングするテンプレートを探し、それをブラウザへと返す。listの表示テンプレートの中身はほとんどが普通のHTMLだ。実際のアクションは、テンプレートのこの部分になる。
<% @recipes.each do |recipe| %>
<tr>
<td><%= link_to recipe.title, :action => "show", :id => recipe.id %></td>
<td><%= recipe.date %></td>
</tr>
<% end %>
この埋め込みRubyコードがコントローラー内のレシピコレクションを繰り返し処理する。テーブルの行の始めのセルは、レシピ表示ページへのリンクを作成する。レシピオブジェクトに使われているアトリビュートに注意してほしい。(title
,
id
, date
)これらは、recipes
テーブルの列名からそのまま名付けられている。
クックブックにカテゴリーを追加する
レシピには、カテゴリー(デザートのような)を指定できるようにしたい。そして、特定のカテゴリーに属するレシピだけを一覧できるようにしたい。これをできるようにするためには、データベースへのカテゴリーテーブルの追加と、所属するカテゴリーを示すフィールドのレシピテーブルへの追加が必要になる。
MySQL-Frontでcategories
テーブルを作成しよう。自動的に生成されるId
フィールドをid
へと変更するのを忘れないように。そしてname
フィールドをvarchar(50)で作成する。テーブルは
Figure 44のようになるはずだ。
Figure 44. categories
テーブル
さらに、カテゴリーコントローラーとカテゴリーモデルも必要だ。コマンドプロンプトをcookbookフォルダで開いて、コマンドを実行しよう。(Figure 45)
ruby script\generate controller Category
ruby script\generate model Category
Figure 45. カテゴリーモデルとコントローラーの作成
最後に、足場(scaffolding)をカテゴリーコントローラーへ追加しよう。c:\rails\cookbook\app\controllers\category_controller.rb を編集して、Figure 46のように足場(scaffolding)を追加する。
Figure 46. カテゴリー用のscaffold
ブラウザでhttp://127.0.0.1:3000/category/new
を開いて、二つのカテゴリーSnacks
とBeverages
を作成しよう。それが終わったら、Figure
47のように見えると思う。
Figure 47. すべてのカテゴリーの一覧