Rails 2.0とFlex 3 beta3でRESTfulなBookmarkアプリを作ろう 3
今回は前回の最後にでてきた問題(新規追加時のエラー)とその回避方法についてまとめます。
問題の説明
Bookmarkを新規追加すると、エラーのダイアログが表示されます。
でも、最新のリストを再取得してみるとBookmarkの追加自体は成功しています。
つまり、新規追加の処理自体は成功しているのに、誤ってエラーダイアログが表示されるということです。
原因
HTTPステータスコード「201 Created」の扱いについてRailsとFlexにずれがあることが原因です。一般的なWebアプリにおいて、通常クライアントのリクエストが成功した場合はHTTPステータスコード「200 OK」が返されますが、RailsのRESTfulアプリにおいて新規生成(PUT)が成功したときは、201が返されるようです。ところが、Flexが201を受け取るとエラーとして処理してしまいます。
これをFlexのバグとして報告しましたが、微妙なとこではあります。というのは、201はHTTPのPUTメソッドが成功したときに返されるものと定義されるようですが、Flex(Flash Player)ではPUTメソッドは送信できません(GETとPOSTのみ可)。これは一般的なブラウザでも同じです。そこでRailsのRESTfulアプリではパラメータに"_method=PUT"が含まれたPOSTメソッドでPUTメソッドの代用ができることを利用して擬似的にPUTを実現しています。つまり実際Flexから送信されているのはPOSTメソッドなのでそのレスポンスにおいてFlexが201を考慮していないのは仕方が無いとも言えます。
ただ、今後FlexがRESTfulアプリのクライアントとして重要な地位を占めるためにも、これはぜひ対応してほしいとこです。FlexからPUTやDELETEをプロキシサーバなしに送信可能になったらなおよいですが。それはFlash Playerの制限で無理そうです。
回避方法
Flex側でHTTPServiceの代わりに、URLLoaderを使って、HTTPStatusEventを取って(この場合もioErrorになる)201の場合、例外処理をする手もあるが、ブラウザによっては取れない場合もあるらしいので、サーバ側で対応した方がいいでしょう。
つまり、現在201を返しているとこを修正して200を返すようにします。修正するファイルは[RAILS_ROOT]\app\controllers\にあるbookmarks_controller.rbです。これを以下のように修正します。
# bookmarks_controller.rb抜粋
# POST /bookmarks
# POST /bookmarks.xml
def create
@bookmark = Bookmark.new(params[:bookmark])
respond_to do |format|
if @bookmark.save
flash[:notice] = 'Bookmark was successfully created.'
format.html { redirect_to(@bookmark) }
#format.xml { render :xml => @bookmark, :status => :created, :location => @bookmark } # 201を返す
format.xml { render :xml => @bookmark, :location => @bookmark } # 200を返す
else
format.html { render :action => "new" }
format.xml { render :xml => @bookmark.errors, :status => :unprocessable_entity }
end
end
end
修正完了
これでRESTfulアプリの基本機能である、一覧取得(GET)、新規追加(PUT)、更新(POST)、削除(DELETE)がエラーなくできるようになりました。
次回は、このアプリをレンタルサーバのXREAにアップしてアプリを公開するとこまでやりましょう。
トラックバック(0)
このブログ記事を参照しているブログ一覧: Rails 2.0とFlex 3 beta3でRESTfulなBookmarkアプリを作ろう 3
このブログ記事に対するトラックバックURL: http://uenon.jp/mt/mt-tb.cgi/101

Rails 2.2.2で,サンプルを試すと,更新(PUT)と削除(DELETE)でエラーが出ます.理由は,PUTとDELETEを
行う際に,authenticity_tokenの値をセットしていないためのようです.これは,Railsの新しいversionから利用されるようになった認証の機構のようです.
そこで,authenticity_tokenの値を,bookmark.mxmlに渡してやらなければいけないわけです.
その為に,私のとった方法は,
(1) flex.htmlのファイルを,Rubyが生成する(html.erbのファイルの1つにする)ようにします.
そして,その中で,FlashVarsをセットします.objectタグの中は
<param name="FlashVars" value="auth=<%= form_authenticity_token %>"
とembedタグの中では
FlashVars="auth=<%= form_authenticity_token %>"
これで,bookmark.swfファイルで,authenticity_tokenの値を得ることができます.
(2) bookmark.mxmlのプログラムにFlashVarsの値を得る部分を追加します.
var flashvars:Object;
var auth:String;
flashvars = LoaderInfo(loaderInfo).parameters;
auth = flashvars["auth"];
これで,authという変数に,authenticity_tokenの値が入ります.
(3) authenticity_tokenの値をPUT, DELETEのリクエストの値に追加する.
request["authenticity_token"] = auth;
以上で,PUT, DELETEもエラーなく動作すると思います.
丁寧な情報共有ありがとうございます。