AjaxOnRails
http://www.onlamp.com/pub/a/onlamp/2005/06/09/rails_ajax.html の 日本語訳です。 訳者の私見が入りまくりですが、気に入らない場合は消してください。はい。ちなみに大括弧内は訳者の感想です。
Ajax on Rails
by Curt Hibbs[懐かしいな] 06/09/2005
translated by speakillof
ここ2・3ヶ月の間で Ajax は 曖昧であまり使われていない技術から本当に本当にホットなものになりつつあります。この記事では Ruby on Rails という Web アプリケーションフレームワークの一部としてサポートされることで 信じられないくらい簡単に Ajax を使うことができることを紹介します。今回は一歩一歩段階を踏むチュートリアルではありません。この記事を書くにあたって私は皆さんが Rails で Web アプリケーションを構成したり、作ったり[最悪な訳だ]する事を多少知っている事と仮定します。もし、補習を必要とするならば Rolling with Ruby on Rails Part 1 と Part 2 をチェックしてみてください。
みなさんの船が座礁して今年のほとんどを遠い島ですごした場合に備えて、ここでAjaxの歴史を60秒くらいで紹介します。
はじめに World Wide Web がありました。デスクトップアプリケーションに比べて Web アプリケーションは遅くてかっこ悪いものでした。でも、とにかくもみんな Web アプリケーションが大好きでした。なぜなら、ブラウザーのあるコンピューターからならどこからでも Web アプリケーションを便利に使うことが出来たからです。あるとき、Microsoft が IE5 で XMLHttpRequest を創りだしました。それはブラウザーで実行される Javascript が 新しいページを表示させること無くバックグラウンドで Web サーバーと通信することを可能にするものでした。これは Web アプリケーションにさらなる柔軟性と応答性[最低な訳だ]を提供しました。まもなく Mozilla にも XMLHttpRequest が実装され、アップルもSafariで実装しました。Operaもその流れに乗りました。
XMLHttpRequest は Web の奥深くにしまわれていた秘密の一つであったに違いありません。1998年の XMLHttpRequest の初公開から、XMLHttpRequest を使ったサイトはほとんどなく、開発者もほとんどいませんでしたし、もし知っていたとしても使わなかったでしょう。Google がその状態を一変させました。Googleg が XMLHttpRequest によって洒落た UI を持つ Web アプリケーション群をリリースしていったのです。その中でもっとも視覚的な印象の強いものは Google Maps でした。このアプリでは皆さんは小さな地図用のウィンドウで操作するにもかかわらず限りなく広い地図をドラッグしているような錯覚を与えてくれます。
Google の優れた XMLHttpRequest の使い方によって XMLHttpRequest が Web アプリケーションの UI を改善することが可能だという事がはっきりと証明されました。その一方で、Jesse James Garrett の2/18のエッセイでついにこの技術に名前が付けられました、その名前こそ Ajax(Asynchronous JavaScript and XML) です。これが先鞭となりました。その名前を知るまで、私達の業界はそれを待ち続け、その新しい名前、Ajaxは山火事のように広がっていきました[名前重要]。私は新しい技術のあだ名がこれほど早く全世界的に採用されることを見たことがありません。
古典的な Web アプリケーション VS. Ajax アプリケーション
「新しいアイテムをリストに追加する」というケースを通じて Ajax Web アプリケーションの本質を紹介させてもらいます。
典型的なインターフェースでは現在のリストとその下に入力用のフィールドが表示されます。入力用のフィールドにはユーザーが新しい名前のテキストを入力します。「新しいアイテムを作る」というボタンをユーザーが押すと、アプリケーションは実際に新しいアイテムを作成し、それをリストに挿入します。
この時点で古典的な Web アプリケーションでは入力用フィールドの値をサーバーに送信します。値を送信されたサーバーは送られてきたデータに従ってその振る舞いを決定し(普通はデータベースをアップデートします)、 別の Web ページを Web アプリケーションに送信します(このページは新しいアイテムを持つリストを表示します)。この方法はたくさんの帯域を必要とします。なぜなら、新しく送信されるページのほとんどは元のページとまったく同じだからです。この Web アプリケーションのパフォーマンスは表示するリストが長くなるにつれ低下します。
対照的に Ajax Web アプリケーションでは入力フィールドの値をサーバーにバックグラウンドで送信して現在表示しているページのうち影響のある部分にアップデートを行います。この方法はユーザーインターフェースの応答性を劇的に改善し、ユーザーにデスクトップアプリケーションを使っているかのように感じさせることが出来ます[訳はいい加減]。
皆さんは実際にこれを自分で見ることが出来ます。下の二つは違う Web 日記へのリンクになっていて、一方はAjax を使ってコメントを送信し、もう一方は Ajax を使いません。試しにそれぞれページに何らかのコメントを送信してみてください。
Ajax はユーザーの使い勝手に関するものです。他の技術やテクニックと同じようにそれを良いようにも悪いようにも使うことが出来ます。この記事で Ajax の使い方を示した後、私はいつ Ajax を使うべきでいつ使うべきでないかそのガイドラインを示そうと思います。
みなさんの Web アプリケーションでAjaxを使う方法
みなさんの Web アプリケーションで Ajax を使う方法の中でつらい方法の一つは XMLHttpRequest オブジェクトの API を直接使って自分用の Javascript を書くことです。これを実行するには各ブラウザーの癖を自分で対処しなければなりません。
より簡単な方法はブラウザー間の差異を隠し、Ajax を使うためのハイレベルな方法を提供してくれる Javascript のライブラリを使うことです。そういったライブラリとして DWR, Prototype, Sajax, Ajax.NET はすべて良い選択肢となります。
すべての中でもっとも簡単な方法は Ruby on Rails に組み込まれている Ajax の機能を使うことです。実際、Railsは、典型的な場合にはAjaxを使わないとき以上に難しくならないくらいAjaxの扱いを簡単なものにしてくれます!
Rails における Ajax の実装
Ajax操作をどう実装するかについて、Railsは単純で一貫したモデルを持ちます。
一度ブラウザーが最初の Web ページを描画して表示させると、ユーザーのアクションはブラウザーに新しいページを表示させるか(この場合は古典的な Web アプリケーションと同じようになります)、Ajax の操作の引き金となります。
1 引き金となるアクションが起きる。引き金になるアクションとしてはユーザーがボタンやリンクをクリックしたり、ユーザーがフォームのデータを変更したり、単純に周期的に実行されたり(タイマーを使います)、といったものです。
2 引き金となるアクションに結びついたデータ(例えばフォームのフィールドの値やフォームの全体の値)は XMLHttpRequest を通じて非同期でサーバー上のアクションハンドラーに送られます。[action handlerって分かりにくすぎ。Rails であれば、要は Ruby のメソッド]
3 サーバーサイドのアクションハンドラーはサーバーに送られてきたデータに基づいていくつかのアクションを実行します(そういうわけでアクションハンドラーと呼ばれます)。そして、HTML の断片を応答として返します。
4 クライアントサイドの Javascript(これは Rails が自動生成します) が サーバーで生成された HTML の断片を受け取って、それを使って現在表示されているページの特定の部分をアップデートします。しばしば アップデートされる部分は div タグの中身になります。
[これって基本的には普通の Ajax の流れ。違うのは Javascript の自動生成]
サーバーへの Ajax リクエストに対して任意のデータを返すことが出来ます。しかし、私は HTML の断片についてのみ話すことにします。実際の美しさは Rails が Ajax を使うためのこの流れを Web アプリケーションの中でどれほど簡単に実装できるのかという点にあります[訳は適当ー]。
link_to_remote の利用
View テンプレートの中で Ajax を使うために Rails はいくつかのヘルパーメソッドを用意しています。最も簡単でかつ非常に利用の幅が広い方法の一つが link_to_remote() です。時刻を求める簡単な Web ページを考えてみましょう。このページには二つのリンクがあって、ユーザーは現在の時刻を得るためにそのリンクをクリックします。時刻を取得してそれをページに表示させるために Web アプリケーションは link_to_remote() を介して Ajax を利用します。
この場合の View テンプレート(index.html)はこんな感じです。 [どうでも良いけど eRuby 以外だとどうなるのこれ?]
<html>
<head>
<title>Ajax Demo</title>
<%= javascript_include_tag "prototype" %>
</head>
<body>
<h1>What time is it?</h1>
<div id="time_div">
I don't have the time, but
<%= link_to_remote( "click here",
:update => "time_div",
:url =>{ :action => :say_when }) %>
and I will look it up.
</div>
</body>
</html>
上のテンプレートには二つの興味深いヘルパーメソッドが存在しています。javascript_include_tag() は Prototype という Javascript のライブラリを使用可能にします。すべての Rails の Ajax の機能はこの Javascript のライブラリを使用しています。利便性のために Rails にはこの Prototype というライブラリが含まれています。
ここで呼ばれている link_to_remote() はもっとも簡単な形で、三つのパラメーターがあります。
1 リンクとして表示される文字列(この場合は click here)
2 DOM のエレメントの id 属性。ここに指定されている id 属性の中身がアクションの実行結果と置き換わります。(今回は time_div の中身が置き換わることになります)
3 実行されるサーバー側のアクションのURL(この場合に呼ばれるアクションは say_when です)
Figure 1. Before clicking on the link
controller クラスは下のようになります。
class DemoController < ApplicationController
def index
end
def say_when
render_text "<p>The time is <b>" + DateTime.now.to_s + "</b></p>"
end
end
Figure 2. After clicking on the link
index アクションハンドラーには何も含まれていません、そのため Rails は index というアクションがある事と index.rhtml というテンプレートを描画すれば良いということだけを認識します。say_when というアクションは現在の日付と時刻を含んだ HTML の断片を生成します。Figure 1 と 2 は click here というリンクをクリックする前と後でどのように index ページの見た目が変化するを示しています。
click here というリンクをクリックすると、ブラウザーは XMLHttpRequest のリクエストを生成し、それを say_when というアクションハンドラー を実行する URL に送ります。そして、say_when というアクションハンドラーは現在の時刻を含んだ HTML の断片を返します。クライアントサイドの Javascript はこの値を受け取って、id 属性が time_div になっている <div> の中身を置き換えます。
アクションハンドラーの返す値で元のデータを置換する代わりに挿入することも可能です。
<%= link_to_remote( "click here",
:update => "time_div",
:url => { :action => :say_when },
:position => "after" ) %>
オプションの :position => "after" というパラメーターを追加しました。これは Rails に目標となるエレメント(この場合は time_div という id 属性を持つ div タグ) の後ろに返ってきた HTML の断片を挿入します。position パラメーターには before, after, bottom, top という値を使うことが出来ます。top と bottom は目標となるエレメントの内側に挿入を行いますが、before と after は目標となるエレメントの外側に挿入します。
どのような場合であっても、position パラメーターを付けたので、click here というリンクは消えることがありません。だから、そのリンクを何回でもクリックして新しいアイテムが追加されるのを見ることが出来ます。
http://www.onlamp.com/pub/a/onlamp/2005/06/09/rails_ajax.html Figure 3. The position option inserts new content
Web ページとしては変化はなく、ブラウザーで表示されている URL にも変化がありません。このような平凡な例であれば、ページ全体のリロードと大きな差はありません。みなさんがもっと複雑なページ、例えばページの一部分だけをアップデートする、 を作るようになればこの差はより顕著になります。
form_remote_tag の利用
form_remote_tag() は 1点を除けば link_to_remote() に似ています。その例外とは form_remote_tag() が HTML のフォームの内容も送信するということです。これはアクションハンドラーがユーザーの入力したデータからレスポンスを生成することが出来るということです。この例ではリストとフォームをもつ Web ページを表示します。そのフォームは Ajax を使って ユーザーがリストにアイテムを追加することを可能にします。
View テンプレート(index.rhtml) はこんな感じです。
<html>
<head>
<title>Ajax List Demo</title>
<%= javascript_include_tag "prototype" %>
</head>
<body>
<h3>Add to list using Ajax</h3>
<%= form_remote_tag(:update => "my_list",
:url => { :action => :add_item },
:position => "top" ) %>
New item text:
<%= text_field_tag :newitem %>
<%= submit_tag "Add item with Ajax" %>
<%= end_form_tag %>
<ul id="my_list">
<li>Original item... please add more!</li>
</ul>
</body>
</html>
Notice the two parts in bold. 二つの部分が重要になります。それぞれはフォームの初めと終わりを定義します[form_remote_tag()とend_form_tag()]。form_tag() の代わりに form_remote_tag() で始まっているので、このアプリケーションは XMLHttpRequest を使ってフォームのデータの送信を行います。form_remote_tag() のパラメーターは見慣れたものであるはずです。
- update パラメーターには DOM のエレメントの id 属性を指定します。ここに指定されている id 属性の中身がアクションの実行結果と置き換わります。(今回は my_list です)
- 実行されるサーバー側のアクションのURL(この場合に呼ばれるアクションは add_item です)
- position パラメーターにはアクションで返ってきた HTML の断片を挿入される位置を指定します。この場合は my_list という id 属性を持つエレメントの先頭にされます(実際は <ul> タグの中)
Figure 4. Before adding any items
Controller はこんな感じです。
class ListdemoController < ApplicationController
def index
end
def add_item
render_text "<li>" + params[:newitem] + "</li>"
end
end
フォームの newitem というテキストフィールドにユーザーがどんなテキストを入力しても add_item アクションハンドラーは 入力された値を リストのアイテムとして持つ HTML の断片を生成します。
Figure 5. After adding several new list items
Observersの利用
Rails ではあるフィールドの値を監視することができます。監視されているフィールドの値が変化した時には Ajax を使ってアクションハンドラーを呼び出すことが出来ます。監視されているフィールドの現在の値が[CGIの] POST のデータとしてアクションハンドラーに送信されます。[やってないからわかんないー]
これの最もありふれた使い方は live search です。
<label for="searchtext">Live Search:</label>
<%= text_field_tag :searchtext %>
<%= observe_field(:searchtext,
:frequency => 0.25,
:update => :search_hits,
:url => { :action => :live_search }) %>
<p>Search Results:</p>
<div id="search_hits"></div>
このコードは searchtext というテキストフィールドの値を監視します。毎0.25秒ごとに Rails はフィールドの値が変化していないかチェックします。もし、フィールドの値が変化していれば、ブラウザーは Ajax を介して live_search アクションハンドラー を実行し、その結果を search_hits という id 属性を持つ div タグに表示します。
みなさんはこの live search のデモを 私の日記 で見ることが出来ます。検索用のボックスが右上の隅にあります。試しに enterprise や rails と打って、何が表示される見てください。
使うべき?使わないべき? (つまり Ajax のこと)
みなさんが Web ぺージの一部をアップデートするために Ajax を使うと、ユーザーは応答性と柔軟性を得ます。しかし、ユーザーはそのページにブックマークを付けられなくなり、ブラウザーの「戻る」ボタンも使えなくなります。これら二つは同じ事実が原因です。ブラウザーが新しいページをロードしていないので、表示する URL が変化しないという点です。
Ajax がクールだからという理由だけで使うのは止めましょう。自分の作る Web アプリケーションのユーザーインターフェースにおいて意味があるかどうかを考えましょう。
例えば、もし、ある Web ページが口座リストを表示し、そこに表示されているリストに対して一連の操作、追加・消去・口座名の変更など、を行う場合、Ajax を使う良い対象といえます。一方で、ある口座に対するすべての請求を表示するリンクをユーザーがクリックした場合、その時は Ajax を使うのを止めて新しいページを表示させるべきです。
これはユーザーが口座のページと請求書のページにブックマークすることやそれらのページの間で「戻る」「進む」ボタンを使うことを可能にさせます。[Ajax を使った場合]ユーザーはこれらのリストの1つに対して操作を行っている時にブックマークを付けたり、リストに対する操作を取りやめにしようとして「戻る」ボタンを使ったりすることはできません(古典的な Web アプリケーションでもこれらの操作はみなさんも阻止したいと思うでしょう)。
がらくた
いけてる例をいくつかとりあげてみなさんの気を引いてみたいと思いますが、詳細には立ち入らないことにします。
アップロードの出来る Web ページではしばしばユーザーは不満を感じます。なぜなら、アップロードが進行している間にユーザーは進行状況に対して何も情報が得られないからです。Ajax を使うことでアップロート中でもサーバーと通信してアップロードしているファイルの状況を取得してその状況を表示させることが出来ます。Sean Treadway と Thomas Fuchs は Rails を使ってこのデモを実装し、それをどのように実装するかというビデオがあります。
Rails で使用している Prototype という JavaScript のライブラリはたくさんのビジュアルなエフェクトも実装しています。そのエフェクトのデモページ には Prototype ライブラリでのエフェクトの使い方とそのデモがいっしょに示されています。
みんさんがこれらのことや Rails の Ajax の機能についてより詳しく知りたい場合、Agile Web Development with Rails の 18章を読んでくさい。[18章は無料で読めますが、これと同じくらいの説明だったような違ったような・・・]
考えを分離する[恥ずかしい訳だな]
個々の Web site が静的なページを提供する時代から Web は長い道のりを経てきました。サイトが動的につながるという新しい時代に私たちは徐々に動いていっています。Web の API は既存のサービスの上に簡単に新しいサービスを構築することを可能にします。そして、ユーザーインターフェースはより柔軟により早く応答できるようになっています[GUIもそうだけど、Ajax は盲の人には最悪だろうなー]。この勃興しつつある Web 2.0 という物語において Ajax は重要な役割を果たしますが、それだけではりません。人々にとって何が Web アプリケーションとして受け入れられるのか Ajax はそうしたことに関しても考えを促すでしょう。
本来、複雑な Ajax の機能を Web アプリケーションに追加するには、多くの余分な労力を必要としますが、Rails はそれをごくシンプルにしてくれます。
Resources
Web sites
- Official Ruby home page
- Official Ruby on Rails home page
- Rails Ajax API
- Download the Rails source code used to create the screenshots in this article.
Mailing lists
Author
Curt Hibbs is a senior software developer in Saint Louis, Missouri, with more than 30 years' experience in platforms, languages, and technologies too numerous to list.
This article is translated by speakillof, who is foolish enough to translate it. Because he is one of the developers of CGIKit, he must write the CGIKit's document instead of tranlation of Rails document. By the way, speakillof is not given permission to translate this article. If someone complains about it, he will remove it from this wiki.
Keyword(s):
References: