次に、カテゴリ切り替えのタブを、現在表示しているカテゴリがアクティブになるように変更します。例えば、「動物Tシャツ」カテゴリがアクティブな場合は、次のようなマークアップになるようにします。
<li class='category active'>動物Tシャツ</li> |
タブはパーシャルで実現されているので、パーシャルに現在アクティブなカテゴリのCategoryインスタンスを渡し、パーシャル内で、現在描画中のカテゴリがアクティブかどうかを判定して描画し分けるようにします。
localsオプションにハッシュを指定すると、パーシャル内で指定した変数が参照できます(参考:renderメソッドのリファレンス)。
<ul id='categories'> |
パーシャル内では、下記のようにactive_category変数と、現在描画中のカテゴリを比較しアクティブかどうかを判定します。
<% |
ここで決定したclass_valueで、<li>を描画します。
<li class='<%= class_value %>'> |
これで、アクティブなタブを表現できました。
次に、RJSでタブの<li>のclassも変更できるようにして、アクティブなタブもRJSで切り替えるようにします。
まず、<li>に「category_現在のID」という値で、idを付けて、RJSで<li>タグの操作が行えるようにしました。
<li class='<%= class_value %>' |
次に、RJSに次の記述を追加して、タブがクリックされたら、一度すべてのタブを非アクティブにします。
<li class='<%= class_value %>' |
その後、現在のカテゴリのみをアクティブにします。
page.select("#category_#{@category.id}").each do |cate| |
selectは、CSSパターンを引数で受け取り、検索された要素に対して処理をすることができるメソッドです(参考:selectのリファレンス)。selectの結果に対してブロック付きでeachを呼び出していますが、これがprototype.jsのeachを無名関数で呼び出す記述に書き換わります(参考:prototype.jsのeachのリファレンス:)。
これはRJSのコレクションプロキシという機能です(参考:RJS Element and Collection Proxies)。結果的に、次のJavaScriptが生成されます。
$$(".category").each(function(value, index) { |
これで、RJSでもアクティブなタブを表現できました。
ここからは、カテゴリ内商品を表示できるようにしていきます。次の手順で説明していきます。
カテゴリのときと同様に、scaffoldで商品の一覧表示や追加、修正、削除などができるようにしてから、カテゴリ詳細画面で商品一覧を呼び出すようにします。商品(product)は、商品名(name)や画像のURL(image_url)、価格(price)の情報を持つことにします。次のようにscaffoldを実行しました。
$ script/generate scaffold product name:string image_url:string price:integer |
次にマイグレーションを使って、カテゴリのときと同様にデータベース上にテーブルを作成します。カテゴリと商品には、「1つのカテゴリに複数の商品が登録される」という1対多のリレーションがあります。このため、データベースのproductsテーブル上に、categoriesテーブルのidカラムへの外部キー参照が必要です。
productsテーブルに外部キー参照を追加するために、「db:migrate」のrakeタスクを実行する前に、scaffoldで生成された「db/migrate/20080929023746_create_products.rb」に次の行を追加します(参考:refencesのリファレンス)。
create_table :products do |t| |
追加したら「db:migrate」を実行します。
$ rake db:migrate |
生成されたproductsテーブルの構造を、sqliteコマンドを使って確認しましょう。
$ sqlite3 db/development.sqlite3 |
「category_id」というカラムが存在します。これで、カテゴリテーブルと商品テーブルのリレーションの設定はできました。
次に、ActiveRecordの「アソシエーション」という機能を使用し、モデルクラス間のリレーションを設定します。CategoryクラスとProductクラスに、次の記述を追加します。
class Category < ActiveRecord::Base |
app/model/category.rb |
class Product < ActiveRecord::Base |
app/model/product.rb |
アソシエーションを設定すると、そのモデルクラスに、関連付けられたモデルを簡単に処理するためのメソッドが追加され、プログラミングがより楽になります。
次に、カテゴリのときと同様に、商品のサンプルデータをtest/fixtures/products.yml内にYAML形式で記述します。商品はカテゴリに所属するので、次のようにサンプルデータ上で所属するカテゴリ情報を指定します。
owl: name: ふくろう image_url: animal/owl.gif price: 1500 category: animal |
test/fixtures/products.yml |
「category」のカラムに指定している「animal」は、前回記事でカテゴリのサンプルデータを登録する際に指定していたレコードの識別名です。
animal: name: 動物Tシャツ description: さまざまな動物の写真をあしらったTシャツです |
test/fixtures/categories.yml |
このように、リレーションの関係にあるレコードを識別名で指定できる機能はFoxy Fixturesなどと呼ばれています。products.ymlを作成したら、rakeタスク「db:fixtures:load」を実行して、サンプルデータを登録します。
$ rake db:fixtures:load |
商品「ふくろう」とひも付けられたカテゴリの情報を確認してみましょう。
$ sqlite3 db/development.sqlite3 |
これで、商品とカテゴリをひも付けながら商品を登録できました。scaffoldが生成される商品一覧画面を見てみましょう。
Copyright © ITmedia, Inc. All Rights Reserved.