それでは、カテゴリ詳細画面に、そのカテゴリに所属する商品の一覧を埋め込みます。表示される商品一覧は、Categoryモデルクラスにhas_manyアソシエーションを設定することで追加された、「@category.products」を利用することで簡単に取得できます。
カテゴリ詳細画面のビューの中で、パーシャルを使って商品一覧を描画させてみましょう。
<div id='products'> |
パーシャルは次のようにしました。
<div class='product'> |
image_tagは、<img>タグを生成するヘルパメソッドです(参考:image_tagのリファレンス)。product_counterは、繰り返し描画のうち、現在の何回目の描画かを返すメソッドです。3回目ごとに、「
」を入れて、改行させています。
ここまでで、カテゴリ内商品が表示されました。
表示するカテゴリを変更した際、カテゴリ名や説明文と同様に商品一覧もRJSで書き換わるようにします。これもshow.js.rjsに、次の記述を追加するだけで実現できます。
page[:products]. |
このようにreplace_htmlメソッドでは、前回記事でも説明した「renderメソッド」と同じ引数を受け取り、パーシャルなどで描画させた結果で、DOM要素の置き換えをすることも可能です。
次に、RJSを使って商品の切り替え時にBlindDownエフェクトを掛けてみます。show.js.rjsに次の行を追加します。
page[:products].visual_effect(:blind_down, |
visual_effectの第2引数には、エフェクトの掛かり具合を調整するパラメータを指定できます。このパラメータはそのままscript.aculo.usのEffectクラスに渡ります(参考:visual_effectのリファレンス)。
ここでさらに、BlindDownエフェクトに連載「パターンとライブラリで作るAjaxおいしいレシピ」の第4回「Ajaxの弱点を補うscript.aculo.usの楽しいエフェクト」で紹介した独自のTransition(パラメータの変化スピードを変える)である「easeOutBounce」を設定してみましょう。
独自のTransitionは、script.aculo.usのEfect.TransitionsにJavaScript関数を追加する必要があります。ですが、このようなJavaScript関数の定義をRJSで行うのは困難なので、JavaScript関数は通常の.jsファイル内に記述し、RJSは、この定義済み関数を利用するようにします。独自のJavaScript関数などは、「public/javascripts/application.js」に記述します。
Effect.Transitions.easeOutBounce = function(pos) { |
作成したtransitionでvisual_effectを呼び出すには、次のようにします。
page[:products].visual_effect(:blind_down, |
このように、関数名などはliteralを通じて渡す必要があります(参考:literalのリファレンス)。
次に、JavaScriptが利用できないクローラなどにも対応できるように、link_to_remoteが生成するタグのhref属性に、カテゴリ詳細画面へのリンクを設定してみます。href属性などのHTML属性値の指定は、link_to_remoteの第3引数にて行います。
<li><%= link_to_remote(category.name, |
これだけで、JavaScriptオフ時の画面表示も確保できました。
最後に、連載「パターンとライブラリで作るAjaxおいしいレシピ」の第6回「Aptana Jaxerで解決するAjaxのSEO対策とは?」でも紹介したSWFAddressを使用し、ここまでのサンプルをディープリンクに対応させてみます。ディープリンクに対応させるには、次の手順で処理します。
ページのロード完了後のJavaScriptの処理はRJSでは制御が困難です(「インラインRJS」という手法がありますが、今回は取り上げません)。RJSで実現が難しいものに関しては、無理にRJSで実装することにこだわらず、application.jsに記述します。
まず、public/javascripts配下に、swfaddress.jsを配置し、/app/views/layouts/categories.html.erb内に下記を追加し、SWFAddressを読み込みます。
<%= javascript_include_tag "swfaddress" %> |
次に、上記手順1に当たる処理を行うために、application.jsに次を追加します。
document.observe("dom:loaded", function() { |
SWFAddress.getPath()は、現在の「#」以降の値からパスの値を返すメソッドです(参考:getPathのリファレンス)。
上記手順2の処理を行うために、show.js.rjsに次の行を追加します(参考:setValueのリファレンス)。
page.SWFAddress.setValue(@category.id.to_s) |
これにより、次のJavaScriptが生成されます。
SWFAddress.setValue("カテゴリID"); |
「page.SWFAddress.setValue」の記述は、RJSの「クラスプロキシ」という機能を利用したものです。これは、pageに渡されたメソッドが、定義済みのメソッドにマッチしない場合、JavaScriptのクラス名にするというものです(参考:クラスプロキシの解説(上部の解説文の最下部にクラスプロキシの説明があります))。
これでサンプルが完成しました。
今回の記事ではRJSの解説をメインに行いました。RJSは、サーバサイドで実行させる内容をすべて生成するため、次のような利点があります。
ただし、複雑なJavaScriptクラスや関数の定義や、クライアントサイドの情報を使ったロジック処理には向いていないケースもあります。このような場合は外部JavaScriptファイルを併用します。
RJSにはここでは解説し切れなかった魅力がまだまだあるので、試してみてはいかがでしょうか。今回のサンプルはこちらからダウンロードできます。ライセンスはGPL 2となります。
Copyright © ITmedia, Inc. All Rights Reserved.