RoRのActiveResourceはPOSTされたデータのcontentTypeを識別します。「application/x-www-form- urlencoded」であればWebブラウザのフォームから、「application/xml」であればXMLデータとして自動的にハッシュに変換します。このためコントローラではどのタイプのデータでPOSTされたのか気にする必要はありません。
しかしFlashでのContentTypeの設定はActionScript 3.0、FlashPlayer 9以上から可能となっており、Flash8以前のバージョンではContentTypeを設定することができません。そのためここでは汎用的に利用するため「lzdata」というパラメータを追加し、ここにXMLデータを設定しています。RoR側は「before_filter」を使用して「lzdata」があればXMLデータとしてハッシュ化するように設定します。
laszlodemo/app/controllers/application.rb
class ApplicationController < ActionController::Base
before_filter :add_lzxdata_to_params
# Pick a unique cookie name to distinguish our session data from
others'
session :session_key => '_laszlodemo_session_id'
def add_lzxdata_to_params
if params.include?('lzdata')
lzdata = Hash.from_xml(params[:lzdata]).with_indifferent_access
params.update(lzdata);
end
end
end
次に、XMLフォーマットでリクエストされた際の正常/異常をXML形式でレスポンスするため、customers_controllerのPOST/PUT/DELETEメソッドを次のように修正します。
laszlodemo/app/controllers/customers_controller.rb(一部)
# POST /customers
# POST /customers.xml
def create
@customer = Customer.new(params[:customer])
respond_to do |format|
if @customer.save
flash[:notice] = 'Customer was successfully created.'
format.html { redirect_to customer_url(@customer) }
format.xml { render :xml => '<ok action="create" />' }
else
format.html { render :action => "new" }
format.xml { render :xml => @customer.errors.to_xml }
end
end
end
# PUT /customers/1
# PUT /customers/1.xml
def update
@customer = Customer.find(params[:id])
respond_to do |format|
if @customer.update_attributes(params[:customer])
flash[:notice] = 'Customer was successfully updated.'
format.html { redirect_to customer_url(@customer) }
format.xml { render :xml => '<ok action="update" />' }
else
format.html { render :action => "edit" }
format.xml { render :xml => @customer.errors.to_xml }
end
end
end
# DELETE /customers/1
# DELETE /customers/1.xml
def destroy
@customer = Customer.find(params[:id])
@customer.destroy
respond_to do |format|
format.html { redirect_to customers_url }
format.xml { render :xml => '<ok action="delete" />' }
end
end
それではLZXに戻り、保存と削除ボタンを追加したrestgridを作成しましょう。<attribute>タグでクラスのプロパティを設定します。ここでは「削除」「保存」ボタンのvisibleとRESTリクエストのURLをプロパティとして作成しました。
次のコードでは新規データ作成用のパブリックメソッド「createdata」と内部で使用するためのプライベートメソッドを作成しています。プライベートメソッドには<!--- @keywords private -->コメントを追加してドキュメントに出力されないようにしています。ただしLZX言語ではprivateの概念がありませんので外部からアクセスすることは可能です。
post/delete/put/getのアクションと対象となるオブジェクトのURLを指定してRESTリクエストするために、下のコード内のrequestメソッドが重要なメソッドとなっています。リクエストの結果をdatapointerでチェックし、異常の場合はデバッグウィンドウにエラーメッセージを表示、正常の場合はリクエストタイプによって必要な処理を追加しています。
restgrid.lzx
<library>
<include href="gridbutton.lzx" />
<!--- REST保存、削除機能が追加されたグリッド -->
<class name="restgrid" extends="grid">
<!--- リクエストベースURL -->
<attribute name="baseurl" value="" type="string" />
<!--- 保存ボタン表示 -->
<attribute name="showsavebutton" type="boolean" value="true" />
<!--- 削除ボタン表示 -->
<attribute name="showdeletebutton" type="boolean" value="true" />
<!--- @keywords private アクションされたデータポインタを保持 -->
<attribute name="_actioneddp" value="null" />
<!-- RESTリクエスト用のデータセット -->
<dataset name="actionds" request="false" />
<gridbutton text="保存" visible="${classroot.showsavebutton}">
<handler name="onclick" args="dp">
classroot.updatedata(dp);
</handler>
</gridbutton>
<gridbutton text="削除" visible="${classroot.showdeletebutton}">
<handler name="onclick" args="dp">
classroot.deletedata(dp);
</handler>
</gridbutton>
<!--- 新規データ作成 -->
<method name="createdata">
this.request("post", "");
</method>
<!--- @keywords private データ削除 -->
<method name="deletedata" args="dp">
var nodeid = dp.xpathQuery("id/text()");
this._actioneddp = dp;
this.request("delete", nodeid + ".xml");
</method>
<!--- @keywords private データ更新 -->
<method name="updatedata" args="dp"><![CDATA[
var nodeid = dp.xpathQuery("id/text()");
this._actioneddp = dp;
this.request("put", nodeid + ".xml");
]]></method>
<!--- @keyword private データリクエスト -->
<method name="request" args="method, obj"><![CDATA[
var p = new LzParam();
switch(method){
case "get": case "GET":
this.actionds.setQueryType("get");
break;
case "post": case "POST":
this.actionds.setQueryType("post");
break;
case "delete": case "DELETE":
this.actionds.setQueryType("post");
p.addValue("_method", "delete");
break;
case "put": case "PUT":
this.actionds.setQueryType("post");
p.addValue("_method", "put");
p.addValue("lzdata", this._actioneddp.serialize());
break;
}
p.addValue("format", "xml");
this.actionds.setSrc(this.baseurl + obj);
this.actionds.setQueryString(p);
this.actionds.doRequest();
]]></method>
</class>
</library>
*restgrid.lzxの「<!--- @keywords private データ削除 -->」の項目の前に、「<!--- 新規データ作成 -->」を追加訂正します。(2007/11/21)
|