Adobe Flex + Ruby on Rails (+ RubyAMF) = ‘RIA Nirvana’

Kilka miesięcy temu wziąłem udział w warsztatach Flex Challenge Academic Tour na których zainteresowało mnie używanie Flex-a jako front end dla aplikacji napisanych w czymś innym. Warsztatowym przykładem było, jak łatwo się domyśleć, PHP jednak mnie zainteresowało użycie railsów. W końcu udało mi się znaleźć trochę więcej czasu i poszukałem materiałów w internecie. Natrafiłem na wpis w blogu Ruby on Rails with Flex i z jego pomocą udało mi się dotknąć rąbka ‘RIA Nirvany’ ;)

Zakładamy projekt, instalujemy plugin RubyAMF który wprowadza szczyptę magii…

1
2
3
rails app
cd app
script/plugin install http://rubyamf.googlecode.com/svn/tags/current/rubyamf

Generujemy rusztowanie i dodajemy jedną linijkę do kontrolera by umożliwić przekazywanie danych z RoR ‘na zewnątrz’:

1
2
script/generate scaffold Photo title:string author:string price:integer
rake db:migrate
1
2
3
4
5
6
7
8
9
10
11
12
13
class PhotosController < ApplicationController  
  # GET /photos  
  # GET /photos.xml  
  def index
     @photos = Photo.all
     respond_to do |format|
       format.html # index.html.erb
       format.xml  { render :xml => @photos }
       format.amf  { render :amf => @photos } # dodana linijka
     end
  end
...
end

Teraz czas na na przygotowanie interfejsu we Fleksie:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    creationComplete="onCreationComplete(event)">
    <mx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.collections.ArrayCollection;
            import com.unitedmindset.vo.PhotoVO;
           
            [Bindable]
            public var photos:ArrayCollection
           
            private function getPhotosList(event:Event=null):void {
                photoRO.getOperation("index").send();
            }
           
            private function onIndexResult(event:ResultEvent):void {
                photos = new ArrayCollection(event.result as Array);
            }  
           
            private function onCreationComplete(event:FlexEvent):void {
                getPhotosList(event);
            }
           
            private function onFault(event:FaultEvent):void {
                Alert.show(event.fault.faultString,event.fault.name);
            }
        ]]>
    </mx:Script>
    <!-- remote objects -->
    <mx:RemoteObject id="photoRO" destination="rubyamf" endpoint="rubyamf/gateway" source="PhotosController" showBusyCursor="true" fault="onFault(event)">
        <mx:method name="index" result="onIndexResult(event)"/>
    </mx:RemoteObject>
    <!-- design -->
    <mx:Panel layout="absolute" left="10" right="10" top="10" bottom="10">
        <mx:AdvancedDataGrid id="photosDG" designViewDataType="tree" dataProvider="{photos}" left="10" right="10" top="10" bottom="10">
            <mx:columns>
                <mx:AdvancedDataGridColumn headerText="Title" dataField="name"/>
                <mx:AdvancedDataGridColumn headerText="Author" dataField="author"/>
                <mx:AdvancedDataGridColumn headerText="Price" dataField="price"/>
            </mx:columns>
        </mx:AdvancedDataGrid>
    </mx:Panel>
</mx:Application>

oraz klasa ‘PhotoVO’ którą umieszczamy w /src/com/unitedmindset/vo/PhotoVO.as:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.unitedmindset.vo
{
    [RemoteClass(alias="PhotoVO")]
    [Bindable]
    public class PhotoVO
    {
        public function PhotoVO()
        {
        }
       
        public var id:int;
        public var title:String;
        public var author:String;
        public var price:int;
        public var createdAt:Date;
        public var updatedAt:Date;
    }
}

Skompilowany plik umieszczamy w folderze Public. Na koniec pozostaje nam przygotowanie pliku konfiguracyjnego dla RubyAMF który znajduje się w /config/rubyamf_config.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
require 'app/configuration'
module RubyAMF
  module Configuration
    ClassMappings.ignore_fields = ['created_at','created_on','updated_at','updated_on']
    ClassMappings.translate_case = true
    ClassMappings.assume_types = false
    ClassMappings.register(:actionscript => 'PhotosVO',
      :ruby => 'Photo',
      :type => 'active_record',
      :attributes => ['id', 'title', 'author', 'price', 'created_at', 'updated_at'] )
    ParameterMappings.scaffolding = true
  end
end

Żeby zobaczyć efekt naszej pracy otwieramy localhost:3000/nazwa_pliku.swf. Oczywiście przykład jest najprostszy z możliwych, ale pokazuje z grubsza jak to wszystko wygląda ;)

1 Response to “Adobe Flex + Ruby on Rails (+ RubyAMF) = ‘RIA Nirvana’”


  1. 1 zabawki edukacyjne maja 8th, 2010 at 13:22

    Bardzo interesujący post. Bez wątpienia wpadnę jeszcze po więcej ciekawych treści.

Leave a Reply