JavaScriptによるRESTライブラリ Jester ver1.3 とJSONP対応 JavaScript Rails REST
2007-06-10
あいかわらず、JavaScriptのActiveResource的なRESTライブラリ Jester を触るのが楽しい
Jester-RESTfullなRails向けJavaScriptライブラリ:TKMR.blog.show
RESTなRails 向けのJavaScriptライブラリ Jester まとめ:TKMR.blog.show
RESTアクセスを行うJavaScriptライブラリ Jester Ver.1.2の変更点:TKMR.blog.show
このJester、最近Subversionのリポジトリを見るとVer1.3が完成している(ように見える)。CHANGELOGを見るとついにJSONサポートが完了してる?早速試してみよう
ローカルサーバとJSON
まずサーバ側を用意、クレジットカードが目に入ったのでcardとかをscaffold_resourceで作る
ruby script/generate scaffold_resource card name:string number:integer
各種アクションをJSON対応させる
respond_to do |format|
format.html
format.xml { render :xml => @cards.to_xml }
format.json { render :json => @cards.to_json}
end
サーバ側終了、rake migrateしてからwebサーバ立ち上げる。
続いてクライアント側、Prototype.jsとJester.jsを読み込ませて準備完了。FireBugで触ってみる
追記:PUT & DELETEはクエリーストリングで擬似的に投げる、_method=put みたいに
Base.model("Card",{format: "json"}); >>> Card.create({name: "Suica", number: 123311123}); POST http://localhost:3000/cards.json ( card[name]=Suica&card[number]=123311123 ) >>> suica = Card.find(3); GET http://localhost:3000/cards/3.json >>> suica.name; "Suica" >>> suica.name = "Pasmo"; >>> suica.save(); POST http://localhost:3000/cards/3.json ( card[name]=Pasmo&card[number]=123311123&card[id]=3&_method=put ) >>> suica.destroy(); POST http://localhost:3000/cards/3.json ( _method=delete )
文句無しの動作:)RESTfulにサーバ側を作っておけばかなり快適、実質書いたコードは10行くらいだろうか?
クロスサイトとJSONP対応
但しJSONといってもあくまでもAjax.Requestを投げ結果をevalするだけ、JSONPでクロスサイトリクエストは無理な様子(正式にリリースされていないので確信は無いですが)やっぱクロスサイトにできると楽しそうなので、まずはfindを実装してみた。あとついでにカスタムメソッドも
<課題>
・findのみではなく更新系も対応(やっぱBase.requestを拡張する?)
・コールバック用の一時的な関数を作るのは微妙...
→動的生成するscriptのonLoadイベントへコールバックを設定するべき?
これで試しに Twitter / Wassr / LivedoorReaderFeedAPI / AmebaVision 等のAPIを叩いてみた
デモ画面こちらから→:http://blog.tkmr.org/jester-13-test.html
以下のようにモデルを宣言して
class="clear"
//Twitter API
Base.model("Statuse",{format:"json", prefix:"http://twitter.com"});
//LDR API
Base.model("LDRFeed",{format:"json", plural:"feed", prefix:"http://rpc.reader.livedoor.com"});
//Wassr API
Base.model("Wassr",{format:"json", plural:"api.wassr.jp", prefix:"http:/"}); //むむむ苦肉の策
//AmebaVision API
Base.model("AmebaVision",{format:"json", plural:"api/get", prefix:"http://vision.ameba.jp"});
findを実行してみる
class="clear"
Statuse.find("friends.json",
{},
{onSuccess: function(base){
render(base, new Template("<img src='#{profile_image_url}'/><a href='#{url}'><h2>Name : #{name}</h2></a><h4>#{description}</h4>"));
}});
LDRFeed.find("discover",
{format:"json", url:"http://www6.ocn.ne.jp/~katoyuu/"},
{onSuccess: function(base){
render(base, new Template("<a href='#{link}'><h2>#{title}</h2></a><h4>subscribers_count:#{subscribers_count}</h4>"));
}});
Wassr.find("public_timeline.json",
{},
{onSuccess:function(base){
render(base, new Template("<a href='#{link}'><h2>#{text}</h2></a><h4>#{user_login_id}</h4>"));
}});
AmebaVision.find("recentMovie.do",
{format:"jsonp"},
{onSuccess:function(base){
render(base[0].item, new Template("<a href='#{link}'><img src='#{imageUrlLarge}'/><h2>#{title}</h2></a>"));
}});
結果が表示される筈。
結局REST度が高いTwitter以外は無理矢理感が否めないか。。。この辺りRESTfulなAPIが増えていけば面白そうだと思う、JesteのやってることはまるでO/R(Object/RESTResource)マッピングだと思うのだが、世界中のWEBサービスがをオブジェクトへマッピングして自由に汎用的に扱えればかなり面白そうだ。上のFireBugでやっているようなことを世界規模でできると楽しいと思うのだけど、どうだろうか?
例えばTwitterの発言でURLを見つけたら、関連するフィードを探してLDRに登録するには
class="clear"
statuses = Twitter::statuse.find("friend_timeline")
statuses.each do |status|
if status.text.isURL? then
feeds = LDR::feed.find("discover", {:url => status.text})
feeds.each do |feed|
LDR::account.find(myid).update("subscribe", {:url => feed.url})
end
end
end
等と書きたい。そのためにSOAPなんて必要ない、シンプルなRESTで十分だと思う。
JavaScriptでMVC
についても書きたかったのだけど、明日に回そう。
最近リリースされたERbテンプレートライクなJavaScriptテンプレートエンジン "EJS" をViewに置いて
EJS - Embedded JavaScript at Edward Benson
ModelはJester、Controllerは...jQuery辺りを組み合わせて、Railsとの連携に向いたシンプルで簡単なMVCフレームワークが作れないかな。プラグイン式に拡張可能なやつが良いな〜、とか考えてる。
追記:正式にリリースされたぽいJester ver1.3の変更点についてメモ
コメント
tkmr「なるほど、コールバックの関数名までキャッシュしやがるんですね。修正してみました。どうかな」


h.t「twitterのデモは動かないですね。原因はこれでしょう http://blog.8-p.info/articles/2007/05/23/twitter-jsonp」