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