RJSなら数行のRubyコードでAjaxアプリを作成できるRuby on RailsのRJSでかんたんAjax開発(後編)(2/4 ページ)

» 2008年10月22日 00時00分 公開
[志田裕樹株式会社アークウェブ]

拡張子「.js」の場合は、RJSでレスポンスする

 前編の「コントローラからビューの呼び出し」のところで解説しましたが、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

…【略】…

    respond_to do |format|
        format.html # show.html.erb
        format.js # show.js.rjs
    end

…【略】…

end

 RailsはJavaScriptのレスポンスを要求される場合は、RJSで記述されたテンプレートを使用します。

RJSテンプレートを作成する

 RJSテンプレートファイルを以下のパスに作成します。

app/views/categories/show.js.rjs
              コントローラ名
                           アクションメソッド名
                                              レスポンス形式

 RJSファイルの内容は次のようにしました。

page[:category_name].replace_html(@category.name)
page[:category_description].replace_html(@category.description)

RJSコードの解説

 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>

<div id='category_description'><%=h @category.description %></div>

RJSが返すレスポンスをWebブラウザで確認

 RJSが返すレスポンスをWebブラウザで直接見てみましょう。URLは以下です。

http://【Railsをインストールしたマシンのアドレス】:3000/categories/【ID】.js

 次のような内容が表示されます(実際には、日本語部分はエンコードされています)。

try {
    $("category_name").update("動物Tシャツ");
    $("category_description").update(
       "さまざまな動物の写真をあしらったTシャツです");
} catch (e) {
    alert('RJS error:\n\n' + e.toString());
    alert('$(\"category_name\").update(\"動物Tシャツ");\n
    $(\"category_description\").update(
       \"さまざまな動物の写真をあしらったTシャツです");');
    throw e
}

 これがクライアント側のeval()関数で実行されます。

生成されたコードのeval()での実行

 link_to_remote()が生成したprototype.jsのAjax.Requestは、「evalScripts:true」が指定されていました。これにより、サーバがRJSで生成したJavaScriptコードがクライアント側で自動的にeval()で実行されます。

 これで、カテゴリ名、カテゴリ説明文がAjaxで切り替わります。

コラム 「RJSで利用可能なメソッド」

「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で利用可能なメソッド

デザインを適用したデモを確認してみる

 ここまでのサンプルに、次の変更を行いデザインに適用します。

  • スタイルシートを更新。それに伴う画像追加
  • show.html.erbのカテゴリ名、カテゴリ説明文を「〜」で囲む
  • EditリンクやBackリンクを削除

RJSで、楽しいエフェクトを掛けよう

 次にカテゴリ名、カテゴリ説明文の切り替え時にAppearエフェクトを掛けてみます。カテゴリ名の変更部分を次のように修正しました。

page[:category_name].
    hide().
    replace_html(@category.name).
    visual_effect(:appear)

 これにより、次のJavaScriptが生成されます。

$("category_name").hide().update("動物Tシャツ")
    .visualEffect("appear");

 visual_effect()メソッドは、script.aculo.usによってElementオブジェクトに追加されたメソッドで、指定された名前のEffectを生成できます(参考:visual_effectのリファレンス)。

 これで、カテゴリ名、説明文を一度に更新してAppearエフェクトを掛けることができました。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。