Using Flex with Ruby on Rails

Posted on March 26, 2008. Filed under: adobe, flex, mxml, rails, ruby, ruby on rails, silverlight, xaml |

This is the second blog post in a series of three posts comparing Flex with Silverlight. In my previous post I demonstrated how to integrate a scaffolded Rails application with Silverlight. Here I will be showing the same with Flex. The steps needed to create the Rails application are also mentioned here.

 

Creating a new Flex project:

Open Flex builder and create a new Flex project.

image

Leave all the options to default and click Finish. A blank project is now created for you.

Add a List control to the default mxml file. It should look like:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
    <mx:List id="userList" width="200" height="200"/>
</mx:Application>

 

Now create a script tag inside the source and add a Bindable element to it:

[Bindable]
private var users:XMLListCollection = new XMLListCollection();

I am using an XMLListCollection because I can easily add/remove elements from it.

 

Now send request to the server and bind the result to the list box:

First create a new HTTPService element:

<mx:HTTPService id="userIndexService" resultFormat="e4x" result="userIndexServiceResult(event)" url="http://localhost:3000/users.xml"/>

 

and handle its result:

private function userIndexServiceResult(event:ResultEvent):void{
    for each(var xml:XML in event.result.user as XMLList){
        users.addItem(xml);
    }
}

 

To invoke this service we need to call its “send()” method with appropriate paramater, which in this case are none.

So the code now looks like:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="sendServiceRequest(event)">
    <mx:Script>
        <![CDATA[
            import mx.rpc.events.ResultEvent;
            import mx.collections.XMLListCollection;
            [Bindable]
            private var users:XMLListCollection = new XMLListCollection();
            
            private function sendServiceRequest(event:Event):void{
                userIndexService.send();
            }
            private function userIndexServiceResult(event:ResultEvent):void{
                for each(var xml:XML in event.result.user as XMLList){
                    users.addItem(xml);
                }
            }
        ]]>
    </mx:Script>
    <mx:HTTPService id="userIndexService" resultFormat="e4x" result="userIndexServiceResult(event)" url="http://localhost:3000/users.xml"/>
    <mx:List dataProvider="{users}" id="userList" width="200" height="200" labelField="name"/>
</mx:Application>

 

And the output looks like:

image

Notice that we are sending the index request in the initialize method of the application.

Now to add controls which show the currently selected element. Its really easy. Just add the folowwing to the code and DataBinding will do the rest:

<mx:HBox>
    <mx:Label text="Name" width="50"/>
    <mx:TextInput text="{userList.selectedItem.name}" width="150" id="userName"/>
</mx:HBox>
<mx:HBox>
    <mx:Label text="Address" width="50"/>
    <mx:TextInput text="{userList.selectedItem.address}" width="150" id="userAddress"/>
</mx:HBox>
 

Now it loooks like:

image

 
Implementing the full CRUD:

Now we need to add the other three HTTPServices.

<mx:HTTPService id="userIndexService" resultFormat="e4x" result="userIndexServiceResult(event)" url="http://localhost:3000/users.xml"/>
<mx:HTTPService id="userCreateService" resultFormat="e4x" result="userCreateServiceResult(event)" method="POST" url="http://localhost:3000/users.xml"/>
<mx:HTTPService id="userUpdateService" resultFormat="e4x" method="POST"/>
<mx:HTTPService id="userDeleteService" resultFormat="e4x" method="POST"/>

 

And their corresponding callbacks.

private function userCreateServiceResult(event:ResultEvent):void{
    users.addItem(event.result as XML);
}

 

Some controls to invoke these services:

<mx:HBox>
    <mx:Button label="Create" id="createUser" click="sendServiceRequest(event)"/>
    <mx:Button label="Update" id="updateUser" click="sendServiceRequest(event)"/>
    <mx:Button label="Delete" id="deleteUser" click="sendServiceRequest(event)"/>
</mx:HBox>

 

And their event handlers (just one in this case):

private function sendServiceRequest(event:Event):void{
    if(event.target.id == 'createUser'){
        userCreateService.send({'user[name]': userName.text, 'user[address]': userAddress.text});
    }else if(event.target.id == 'updateUser'){
        userUpdateService.url = 'http://localhost:3000/users/'+ userList.selectedItem.id +'.xml';
        userUpdateService.send({'user[name]': userName.text, 'user[address]': userAddress.text, _method: 'put'});
        users[userList.selectedIndex].name = userName.text;
        users[userList.selectedIndex].address = userAddress.text;
    }else if(event.target.id == 'deleteUser'){
        userDeleteService.url = 'http://localhost:3000/users/'+ userList.selectedItem.id +'.xml';
        userDeleteService.send({_method: 'delete'});
        users.removeItemAt(userList.selectedIndex);
    }else{
        userIndexService.send();
    }
}

 

Little bit of  knowledge of how REST is implemented in Rails is required to understand the parameters to the     “send()” method of HTTPService class is required, which is out of scope of this blog post.

The TestFrontEnd.mxml should now have the folowwing code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" initialize="sendServiceRequest(event)">
    <mx:Script>
        <![CDATA[
            import mx.collections.XMLListCollection;
            import mx.controls.Alert;
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;
            [Bindable]
            private var users:XMLListCollection = new XMLListCollection();
            
            private function sendServiceRequest(event:Event):void{
                if(event.target.id == 'createUser'){
                    userCreateService.send({'user[name]': userName.text, 'user[address]': userAddress.text});
                }else if(event.target.id == 'updateUser'){
                    userUpdateService.url = 'http://localhost:3000/users/'+ userList.selectedItem.id +'.xml';
                    userUpdateService.send({'user[name]': userName.text, 'user[address]': userAddress.text, _method: 'put'});
                    users[userList.selectedIndex].name = userName.text;
                    users[userList.selectedIndex].address = userAddress.text;
                }else if(event.target.id == 'deleteUser'){
                    userDeleteService.url = 'http://localhost:3000/users/'+ userList.selectedItem.id +'.xml';
                    userDeleteService.send({_method: 'delete'});
                    users.removeItemAt(userList.selectedIndex);
                }else{
                    userIndexService.send();
                }
            }
            
            private function userIndexServiceResult(event:ResultEvent):void{
                for each(var xml:XML in event.result.user as XMLList){
                    users.addItem(xml);
                }
            }
            private function userCreateServiceResult(event:ResultEvent):void{
                users.addItem(event.result as XML);
            }
        ]]>
    </mx:Script>

    <mx:HTTPService id="userIndexService" resultFormat="e4x" result="userIndexServiceResult(event)" url="http://localhost:3000/users.xml"/>
    <mx:HTTPService id="userCreateService" resultFormat="e4x" result="userCreateServiceResult(event)" method="POST" url="http://localhost:3000/users.xml"/>
    <mx:HTTPService id="userUpdateService" resultFormat="e4x" method="POST"/>
    <mx:HTTPService id="userDeleteService" resultFormat="e4x" method="POST"/>

    <mx:List dataProvider="{users}" id="userList" width="200" height="200" labelField="name"/>

    <mx:HBox>
        <mx:Label text="Name" width="50"/>
        <mx:TextInput text="{userList.selectedItem.name}" width="150" id="userName"/>
    </mx:HBox>
    <mx:HBox>
        <mx:Label text="Address" width="50"/>
        <mx:TextInput text="{userList.selectedItem.address}" width="150" id="userAddress"/>
    </mx:HBox>
    <mx:HBox>
        <mx:Button label="Create" id="createUser" click="sendServiceRequest(event)"/>
        <mx:Button label="Update" id="updateUser" click="sendServiceRequest(event)"/>
        <mx:Button label="Delete" id="deleteUser" click="sendServiceRequest(event)"/>
    </mx:HBox>

</mx:Application>

 

This is the end result:

image

As I mentioned in my last blog post it is not the best way to make this application as there is no error handling. But I think this is the simplest way to make this application.

You also might have noticed Flex requires a lot less lines of code as compared to Silverlight. But that is also dependent on my coding approach.

Full code for this application can be downloaded from:

Advertisements

Make a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

5 Responses to “Using Flex with Ruby on Rails”

RSS Feed for Blogging on Technology Comments RSS Feed

[…] Using Flex with Ruby on Rails […]

Any ideas on the following error? I happens when I try to create a new record in the database. The record does get created, but the message pops up in a flash player window…Dismiss All/Continue. Thanks C.K.

[RPC Fault faultString=”HTTP request error” faultCode=”Server.Error.Request” faultDetail=”Error: [IOErrorEvent type=”ioError” bubbles=false cancelable=false eventPhase=2 text=”Error #2032: Stream Error. URL: http://localhost:3000/users.xml“]. URL: http://localhost:3000/users.xml“]
at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::faultHandler()[E:\dev\3.0.x\frameworks\projects\rpc\src\mx\rpc\AbstractInvoker.as:216]
at mx.rpc::Responder/fault()[E:\dev\3.0.x\frameworks\projects\rpc\src\mx\rpc\Responder.as:49]
at mx.rpc::AsyncRequest/fault()[E:\dev\3.0.x\frameworks\projects\rpc\src\mx\rpc\AsyncRequest.as:103]
at DirectHTTPMessageResponder/errorHandler()[E:\dev\3.0.x\frameworks\projects\rpc\src\mx\messaging\channels\DirectHTTPChannel.as:343]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at flash.net::URLLoader/redirectEvent()

[…] CRUD applications can be easily created using Ruby on Rails as the backend and Flex as the frontend app using the XML format as demonstrated here. […]

hello there,
i am a junior programmer in flex.
recently i have started work in flex programming.
i have a problem i think i can get solution from here.
how can i run following application in browser.

http://localhost:3000/dragTile/DragDrop.html

i have download a example from net.
but when i run it by run command in flex builder 3 then above code appears in address bar
how can i run that application
please help me i think you can
thanks

Hi Sonalika,

To configure the url that opens when you run the project right click on the project in Flex Navigator and select “Properties”:
http://skitch.com/gauravsharma/9kii/preview
Select “Flex Build Path”:
http://skitch.com/gauravsharma/9ki7/skitch
and clear the “Output Folder Url” or optionally point it to your server. Just to run the project you should clear the existing value.


Where's The Comment Form?

Liked it here?
Why not try sites on the blogroll...

%d bloggers like this: