FlexibleRails
サーバでRuby on Railsを使ってデータを提供して,Flex(Flash)をクライアントに使ってデータを表示してみる.flexiblerailsと一部で呼ばれているようだ.
- http://www.liverail.net/articles/2006/04/16/rubyonrails-1-1-and-flex-2-0-pt-1
- http://www.liverail.net/articles/2006/5/6/rubyonrails-1-1-and-flex-2-0-pt-2
に沿ってFlexからRuby on RailsにアクセスしてデータのCRUD(Create, Read, Update and Delete)が出来るアプリを作ってみました.
本家に最終系のソースが無いので,貼っておきます.
(操作をしている動画を作ったんだけど,文字が見えなくて何をしているのかわからない・・・orz.)
普通にRuby on Railsを行う時とは,Railsのサーバはブラウザでアクセスする場合と同様に作成するけど,違いは,HTMLを返すのではなくXMLを返すこと(render :xml => ... をするだけ).
Flexの方は,XML形式でデータを作成して,Railsに投げます.Railsでは,普通にRailsを組むときのように,paramsで受け取れます.
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" layout="absolute" creationComplete="reviewRequest.send()"> <mx:HTTPService id="reviewRequest" url="http://localhost:3000/reviews/list" useProxy="false"/> <mx:DataGrid id="dgReviews" x="40" y="85" width="600" height="134" dataProvider="{reviewRequest.lastResult.reviews.review}"> <mx:columns> <mx:DataGridColumn headerText="Title" dataField="title" width="480"/> <mx:DataGridColumn headerText="Author" dataField="author" width="240"/> <mx:DataGridColumn headerText="Score" dataField="score" width="80"/> </mx:columns> </mx:DataGrid> <mx:TextArea x="40" y="245" width="600" htmlText="{dgReviews.selectedItem.text}" /> </mx:Application>
<?xml version="1.0" encoding="utf-8"?> <mx:Panel title="Reviews" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns="*" creationComplete="reviewRequest.send()"> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.events.CloseEvent; private function deleteHandler(event:Event) : void { Alert.show("Are you sure you want to delete this item?", "Delete Item", 3, this, function(event:CloseEvent):void { if (event.detail==Alert.YES) reviewDeleteRequest.send({id: dgReviews.selectedItem.id}); }); } ]]> </mx:Script> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.events.DataGridEvent; import mx.events.DataGridEventReason; private function updateHandler(event:Event) : void { dgReviews.editable=true btnUpdateData.label = "End Updates" btnUpdateData.removeEventListener('click', updateHandler) btnUpdateData.addEventListener('click', endUpdateHandler) } private function endUpdateHandler(event:Event) : void { dgReviews.editable=false btnUpdateData.label = "Update Data" btnUpdateData.removeEventListener('click', endUpdateHandler) btnUpdateData.addEventListener('click', updateHandler) } public function checkUpdate(event:DataGridEvent) : void { if (event != null) { if (event.reason == DataGridEventReason.CANCELLED || event.reason == DataGridEventReason.OTHER ) return; var params:Object = new Object(); params['id'] = event.currentTarget.editedItemRenderer.data['id'] params['review[' + event.dataField +']'] = TextInput(event.currentTarget.itemEditorInstance).text reviewUpdateRequest.send(params); } } ]]> </mx:Script> <mx:HTTPService id="reviewRequest" url="http://localhost:3000/reviews/list" useProxy="false"/> <mx:HTTPService contentType="application/xml" id="reviewCreateRequest" result="reviewRequest.send();" url="http://localhost:3000/reviews/create" useProxy="false" method="POST"> <mx:request xmlns=""> <review> <title>{fTitle.text}</title> <author>{fAuthor.text}</author> <score>{fScore.value}</score> <text>{fText.text}</text> </review> </mx:request> </mx:HTTPService> <mx:HTTPService id="reviewDeleteRequest" result="reviewRequest.send();" url="http://localhost:3000/reviews/delete" useProxy="false"/> <mx:HTTPService id="reviewUpdateRequest" result="reviewRequest.send();" url="http://localhost:3000/reviews/update" useProxy="false" method="POST"/> <mx:DataGrid id="dgReviews" width="800" dataProvider="{reviewRequest.lastResult.reviews.review}" editable="false" itemEditEnd="checkUpdate(event);"> <mx:columns> <mx:DataGridColumn headerText="Title" dataField="title" width="480"/> <mx:DataGridColumn headerText="Author" dataField="author" width="240"/> <mx:DataGridColumn headerText="Score" dataField="score" width="80"/> </mx:columns> </mx:DataGrid> <mx:TextArea id="taReviews" width="800" htmlText="{dgReviews.selectedItem.text}"/> <mx:states> <mx:State name="Create"> <mx:AddChild position="lastChild"> <mx:Form width="800" id="frmCreate"> <mx:FormHeading label="Add a new Review"/> <mx:FormItem label="Title" required="true"> <mx:TextInput width="260" id="fTitle"/> </mx:FormItem> <mx:FormItem label="Author" required="true"> <mx:TextInput width="140" id="fAuthor"/> </mx:FormItem> <mx:FormItem label="Score"> <mx:NumericStepper id="fScore"/> </mx:FormItem> <mx:FormItem label="Text"> <mx:TextArea width="600" height="200" id="fText"/> </mx:FormItem> <mx:FormItem direction="horizontal"> <mx:Button label="Submit" click="reviewCreateRequest.send();currentState=''"/> <mx:Button label="Cancel" click="currentState=''"/> </mx:FormItem> </mx:Form> </mx:AddChild> <mx:SetProperty name="height" value="700"/> <mx:SetProperty target="{cbReviewControlBar}" name="height" value="34"/> </mx:State> </mx:states> <mx:transitions> <mx:Transition id="createTransition" fromState="*" toState="Create"> <mx:Parallel target="{frmCreate}"> <mx:WipeDown duration="1000"/> </mx:Parallel> </mx:Transition> </mx:transitions> <mx:ControlBar id="cbReviewControlBar"> <mx:Button label="Create New" id="btnCreateNew" click="currentState='Create'"/> <mx:Button label="Delete" click="deleteHandler(event);"/> <mx:Button label="Update Data" click="updateHandler(event)" id="btnUpdateData"/> </mx:ControlBar> </mx:Panel>
- サーバ側.app/controllers/reviews_controller.rb
class ReviewsController < ApplicationController def list @reviews = Review.find(:all) render :xml => @reviews.to_xml end def create @review = Review.new(params[:review]) @review.save render :xml => @review.to_xml end def delete @review = Review.find(params[:id]) @review.destroy render :xml => @review.to_xml end def update @review = Review.find(params[:id]) @review.update_attributes(params[:review]) render :xml => @review.to_xml end end
- テーブル作成:原著ではSQLで書いていましたが,rake migrate でやりました.
- db/migrate/001_create_reviews.rb
class CreateReviews < ActiveRecord::Migration def self.up create_table :reviews do |t| t.column :title, :string t.column :text, :text t.column :score, :integer t.column :author, :string end end def self.down drop_table :reviews end end