前編の「コントローラからビューの呼び出し」のところで解説しましたが、Railsは同じアクションメソッドでも、リクエスト時の拡張子によって、レスポンスする際の、テンプレートをHTML用やJavaScript用に切り替えができます(注釈)。
注釈:respond_toメソッドは拡張子指定がない場合は、HTTPリクエストヘッダの「Accept」ヘッダの値に従って描画するテンプレートを判定します。Rails 2.1.0からは、Acceptヘッダで「text/javascript」を最優先にしているため、拡張子「.js」を付けなくともRJSテンプレートがあれば、それが描画に使われます(参考:ActionPackのCHANGELOG)。
先ほどのlink_to_remoteでは、Ajaxによるリクエスト先URLを以下のように、これまでのリンク先に「.js」という拡張子を付けたものに変更しています。
category_path(category) + ".js" |
CategoriesControllerのshow()アクションメソッド内のrespond_to()メソッド呼び出し部分も、次のように変更します。
def show |
RailsはJavaScriptのレスポンスを要求される場合は、RJSで記述されたテンプレートを使用します。
RJSテンプレートファイルを以下のパスに作成します。
app/views/categories/show.js.rjs コントローラ名 アクションメソッド名 レスポンス形式 |
RJSファイルの内容は次のようにしました。
page[:category_name].replace_html(@category.name) |
RJSテンプレート内では、JavaScriptGeneratorクラスの「page」という名前のインスタンスが利用可能で、このインスタンスに対して、「JavaScriptGenerator::GeneratorMethods」のページにあるメソッドが利用可能です。
「page[:category_name]」は、[ ]メソッドの呼び出しを行う記述で、「$('category_name');」に置き換わります([ ]メソッドのリファレンス)。
「JavaScriptGenerator::GeneratorMethods」にある各種メソッドはメソッドチェーンを利用できるので、以下のように、つないでreplace_htmlメソッドの呼び出しができます。
page[:category_name].replace_html(@category.name) |
replace_htmlメソッドは、DOM要素のinnerHTMLを与えられた引数の値で置き換えるメソッドです(参考:replace_htmlメソッドのリファレンス)。
これにより、以下のようなJavaScriptコードが生成されます。
$("category_name").update("動物Tシャツ"); |
これに合わせて、show.html.erbの<h1>や<div>にid値を設定し、「$("category_name")」で正しく参照できるようにします。
<h1 id='category_name'><%=h @category.name %></h1> |
RJSが返すレスポンスをWebブラウザで直接見てみましょう。URLは以下です。
http://【Railsをインストールしたマシンのアドレス】:3000/categories/【ID】.js |
次のような内容が表示されます(実際には、日本語部分はエンコードされています)。
try { |
これがクライアント側のeval()関数で実行されます。
link_to_remote()が生成したprototype.jsのAjax.Requestは、「evalScripts:true」が指定されていました。これにより、サーバがRJSで生成したJavaScriptコードがクライアント側で自動的にeval()で実行されます。
これで、カテゴリ名、カテゴリ説明文がAjaxで切り替わります。
「JavaScriptGenerator::GeneratorMethods」では、[ ]やreplace_htmlのほかにも、さまざまなメソッドがあります。ここでは一部を紹介します。
メソッド | 概要 |
---|---|
replace | 要素も含めた置き換え |
insert_html、remove | DOM要素の挿入・削除 |
show、hide、toggle | DOM要素の表示、非表示 |
select | CSSパターンでの要素検索 |
draggable、drop_receiving | DOM要素のドラッグ&ドロップを有効化 |
delay | setTimeout()による遅延実行 |
call | 任意のJavaScript関数の呼び出し |
≪ | 任意のJavaScript文の実行 |
redirect_to | window.location.hrefによる画面遷移 |
visual_effect | script.aculo.usのEffectの生成 |
literal | JavaScriptリテラル表現を返す |
表 RJSで利用可能なメソッド |
ここまでのサンプルに、次の変更を行いデザインに適用します。
次にカテゴリ名、カテゴリ説明文の切り替え時にAppearエフェクトを掛けてみます。カテゴリ名の変更部分を次のように修正しました。
page[:category_name]. |
これにより、次のJavaScriptが生成されます。
$("category_name").hide().update("動物Tシャツ") |
visual_effect()メソッドは、script.aculo.usによってElementオブジェクトに追加されたメソッドで、指定された名前のEffectを生成できます(参考:visual_effectのリファレンス)。
これで、カテゴリ名、説明文を一度に更新してAppearエフェクトを掛けることができました。
Copyright © ITmedia, Inc. All Rights Reserved.