Rails + Adobe Spry framework for AJAX
2007/03/17
Adobe Labs で Spry という Adobe 製の Ajax フレームワークが公開されています。Adobe によると、Spry とは
The Spry framework for Ajax is a JavaScript library for web designers that provides functionality that allows designers to build pages that provide a richer experience for their users. It is designed to bring Ajax to the web design community who can benefit from Ajax, but are not well served by other frameworks.
であり、つまりは Web デザイナーが利用することを想定した JavaScript ライブラリだそうです。@IT にも記事がありますが、 Spry を使うと XML データから動的なページを生成することができます。しかも、デザイナー対象であることから、JavaScript によるコーディングは必要最低限に抑えられています。
ところで Rails 1.2 には新しいジェネレータとして「scaffold_resource」が追加されています。scaffold_resourceで足場を生成すると、通常の scaffold とは異なり、REST 風味のリソース操作が可能になるというのは以前に書きましたが、scaffold_resource を利用すると、さらにリソースの XML 出力まで可能な足場を生成してくれます。例えば、ブログを開発するために、記事のモデル(Post)とコントローラ(PostsController)を作ったとすると、scaffold_resource の場合、
GET /posts
で記事一覧の HTML を取得することができますが、さらに
GET /posts.xml
とするだけで記事一覧の XML を取得することができます。
ここでやっと本題ですが、scaffold_resource を使うとリソースの XML 出力を簡単に得ることができるので、Spry を使うのも簡単じゃない?と思って使ってみました。
1. Spry をダウンロードする
Adobe Labs から Spry をダウンロードします。Adobe ID が必要になるので、持っていない人は登録が必要になります。
2. Rails プロジェクトを作る
ブログっぽく作ってみましょう。サンプルなので SQLite で簡単に。
$ rails blog -d sqlite3
$ cd blog
$ ./script/generate scaffold_resource Post title:string body:text author:string updated_at:datetime
$ rake db:migrate
$ ./script/server
http://localhost:3000/posts にアクセスしてみましょう。
記事の一覧が表示されました。
今度は http://localhost:3000/posts.xml にアクセスしてみましょう。
記事の一覧が XML で表示されました。ミソは生成された次のコードです。
blog/conf/routes.rb :
22: # Install the default route as the lowest priority.
23: map.connect ':controller/:action/:id.:format'
blog/app/controllers/posts_controller.rb :
7: respond_to do |format|
8: format.html # index.rhtml
9: format.xml { render :xml => @posts.to_xml }
10: end
routes.rb でパラメータ :format が定義されているため、GET /posts.xml したときの「.xml」がパラメータ :format として扱われます。posts_controller.rb ではパラメータ :format の値にしたがって出力形式を振り分けています。
3. Spry で一覧表示する
では Spry を利用していきます。まずは Rails プロジェクトに Spry のライブラリファイルを配置します。ダウンロードした Spry を展開して、include ディレクトリ以下にある .js ファイルを blog/public/javascripts 以下にコピーしました。
次に、アプリケーションで Spry をインクルードしましょう。レイアウトファイルに次の 2 行を追加します。
blog/app/views/layouts/posts.rhtml :
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Posts: <%= controller.action_name %></title>
<%= stylesheet_link_tag 'scaffold' %>
<%= javascript_include_tag 'xpath' %> # 追加
<%= javascript_include_tag 'SpryData' %> # 追加
</head>
SpryData は xpath を利用しているため、xpath を先にインクルードする必要があります。
準備が整ったので、Spry を使っていきます。まずは単純に一覧表示してみましょう。Spry を利用するには、まず XML データをデータソースとして登録する必要がありますので、以下のような JavaScript をビューファイルの先頭に追加しました。
blog/app/views/posts/index.rhtml :
<script language="JavaScript" type="text/javascript">
var dsPosts = new Spry.Data.XMLDataSet("posts.xml", "/posts/post");
</script>
new Spry.Data.XMLDataSet の引数は、一つめが XML の場所で、二つめが XML 中の各記事の位置を指す Xpath です。今回の XML の場合、posts 要素の下に post 要素があり、post 要素が各記事の情報を含んでいるため、post 要素を指す Xpath を指定します。
次に一覧表示です。HTML のなかに Spry 用の属性を埋め込むことで、Spry が動的なページを生成します。元のビューファイルの中の記事一覧を表示するタグの周辺を以下のように変更しました。
blog/app/view/posts/index.rhtml :
<div spry:region="dsPosts">
<table>
<tr>
<th>Title</th>
<th>Body</th>
<th>Author</th>
<th>Updated at</th>
</tr>
<tr spry:repeat="dsPosts">
<td>{title}</td>
<td>{body}</td>
<td>{author}</td>
<td>{updated_at}</td>
<td><%= link_to 'Show', :action => :show, :id => '{id}' %></td>
<td><%= link_to 'Edit', :action => :edit, :id => '{id}' %></td>
<td><%= link_to 'Destroy', {:action => :destroy, :id => '{id}'}, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
</table>
</div>
変更点を見てみると、まず以下の記述が追加されています。
<div spry:region="dsPosts">
これは、「このエリアにはデータソース “dsPosts” の内容を表示するぜ!」という意味の宣言になっています。Spry ではこの div タグで囲まれたエリアを「ダイナミックリージョン(dynamic region)」と呼ぶそうです。
次に、
<% @posts.each do |post| %>
という ERB による繰り返し部分が以下のように変更されています。
<tr spry:repeat="dsPosts">
これは Spry の繰り返し表現で、「”dsPosts” の数だけ繰り返してね」という意味です。
最後に、テーブル内各所に表れる {title} や {body} といった記述ですが、これが各記事の情報になります。{title} と記述した場合、dsPosts 宣言時の Xpath とあわせると、/posts/post/title を参照して記事のタイトルに置換されます。この処理によって {id} には各記事の Rails における主キーである ID を参照できるため、以下のようにして link_to と組み合わせることができます。
<td><%= link_to 'Show', :action => :show, :id => '{id}' %></td>
Spry による置換はクライアントサイドで処理されるため、Rails が {id} といった記述を出力するようにしておけば、このように ERB と組み合わせることもできます。
さて、ここまでで基本的な一覧表示が完成していますので、http://localhost:3000/posts にアクセスしてみましょう。
外見はあまりかわっていませんが、ビューファイルからは ERB による出力を削ったはずなので、これは確かに Spry が出力していることになります。
Spry でソートしてみる
ここで終わると「どこがいいんだ?」となってしまうので、テーブルのヘッダをクリックすると記事をソートできるようにして、ちょっとだけ動的なページにしましょう。
記事をソートするには、データソースオブジェクトの sort 関数を使います。
blog/app/view/posts/index.rhtml :
<th><%= link_to_function 'Title', 'dsPosts.sort("title");' %></th>
<th><%= link_to_function 'Body', 'dsPosts.sort("body");' %></th>
<th><%= link_to_function 'Author', 'dsPosts.sort("author");' %></th>
<th><%= link_to_function 'Updated at', 'dsPosts.sort("updated-at");' %></th>
テーブルの見出しをクリックしたときに sort 関数を呼び出すように、ERB で link_to_function を呼んでいます。sort 関数の引数にソートの基準にするデータ要素名を指定します。これで再度 http://localhost:3000/posts にアクセスしてみましょう。
これでテーブルのヘッダ部をクリックしてみると、おお!ソートされます。やっと動的ページができました。
まとめ
以上でソートできる動的ページを作ることができましたが、Spry には他にもさまざまな機能があって、ページネーションや表示項目のフィルタリング、フォームのオートコンプリートなども同じくらい簡単にできるようです。今回はここで止めておきますが、面白そうなので今後使ってみるかもしれません。
Spry はデザイナー向けとのことですが、それはすなわちロジックとビューが明確に分離されていて、ガシガシとコーディングしなくても動的なビューを作れるということ。だからデザイナーではなくデベロッパーな人々にとっても、コーディング不要なお手軽 Ajax フレームワークとして便利に使えるのではないかと思いました。
今回は Spry を使いましたが、同じように XML をデータソースとして食わせれば、Flex をビューにすることもできるんだろうなーと思うので、Flex にも挑戦してみようかしら、と思ったのでした。