Slides from the talk, demoing the source code from out Flex on Rails book, given on January 22nd at Derailed (the Denver Ruby on Rails user group). Source code is available on http://flexonrails.com
3. Why Flex on Rails?
• You already know “why Rails?”
• Flex is another tool in the toolbox
• Service oriented
4. Agenda
• A bit about Flex
• Highlights and source from the book
• Drinking
5. Flex is...
• Part of Adobe’s Flash platform
• Open Source (framework) and free
6. Flex is...
• A compiler
• An XML language - MXML
• A set of components
7. Flex ...
• A way to write ActionScript declaratively
• Compiles to ActionScript
• ActionScript -> SWF
• Runs in the Flash Player
8. Flex on Rails
• Compiled source - keep
separate
• SWF -> /public during
deployment
• Flex talks to Rails with
XML, JSON, or AMF
9. Development
Workflow
• Open SWF or HTML Wrapper from Public
• HTML Wrapper - can use relative urls
• SWF - Hardcode localhost:3000 :-(
• Either - Load an url from config :-)
10. Codes!
git@github.com:danielwanja/flexonrails.git
• Passing Data with XML
• RESTful Services
• Passing Data with AMF
• Data Visualization
• Building Flex with Rake
• Read the Source!
• Observers in Flex
• Authentication
• Hierarchical Data With AMF
• Advanced Data Grid with Awesome Nested Set
• Server Push with Juggernaut
• Flex and Javascript
• File Upload
11. Passing Data with XML
Rails Person.new(:first_name => 'daniel', :last_name =>
'wanja').to_xml
var person:XML = <person>
Flex <first_name>tony</first_name>
<last_name>hillerson</last_name></person>
Getting <mx:HTTPService id=quot;indexquot;
url=quot;http://localhost:3000/people.xmlquot;
XML to resultFormat=quot;e4xquot; />
Flex index.send()
<mx:HTTPService id=quot;updatequot;
url=quot;http://localhost:3000/people/{id}.xml?_method=putquot;
Sending contentType=quot;application/xmlquot;
resultFormat=quot;e4xquot;
XML to method=quot;POSTquot;
Rails result=quot;index.send()quot; />
02
update.send(person)
12. RESTful Services
HTTP verb URL Controller
GET /accounts/:account_id/positions {:action=>quot;indexquot;,
:controller=>quot;positionsquot;}
POST /accounts/:account_id/positions {:action=>quot;createquot;,
:controller=>quot;positionsquot;}
GET /accounts/:account_id/positions/:id {:action=>quot;showquot;,
:controller=>quot;positionsquot;}
PUT /accounts/:account_id/positions/:id {:action=>quot;updatequot;,
:controller=>quot;positionsquot;}
DELETE /accounts/:account_id/positions/:id {:action=>quot;destroyquot;,
:controller=>quot;positionsquot;}
03
13. Nested Resources
class Account < ActiveRecord::Base class Position < ActiveRecord::Base class Movement < ActiveRecord::Base
has_many :positions, belongs_to :account belongs_to :position
:dependent => :destroy has_many :movements, end
end :dependent => :destroy
end
/accounts/:id
/accounts/:account_id/positions/:id
/accounts/:account_id/positions/:position_id/movements/:id
15. Authentication
• All Flex service calls go through the
browser
• AIR manages cookies
• = Standard cookie based credentials work
fine
16. Hierarchical Data with
AMF
• Works nicely with Awesome Nested Set
• Good for retrieving Object Graphs
• More work when sending Object Graphs
17. Read the Source!
• Flex source is available in Flex Builder
• MXML is compiled to ActionScript
18. Observers in Flex
• Binding is sweet
• {} notation
• BindingUtils
• ChangeWatcher
19. Building Flex with Rake
• Simple shell command to mxmlc
• mxmlc needs to be in the path
20. Flex and Javascript
• HTML *and* Flex is sometimes the right
answer
• Flex Ajax Bridge
• ExternalInterface
21. Advanced Data Grid with
Awesome Nested Set
class Category < ActiveRecord::Base
acts_as_nested_set
def full_xml(builder=nil)
xml = builder ||= Builder::XmlMarkup.new(:indent => 2)
xml.category(:id => id,
:name => name,
:description => description,
:qty_in_stock => qty_in_stock) do
children.each { |child| child.full_xml(xml) }
end
end
end
<mx:HTTPService id=quot;categoriesquot; url=quot;http://localhost:3000/categoriesquot; resultFormat=quot;e4xquot; />
18
22. Server Push with Juggernaut
message to socket
localhost:3000/
1. post to http://
3. push JSON
Nt
messenger/
O cke
message
JS so
h
us e to
p
3. sag
es
m
2. send_to_channels
Juggernaut
Rails Application
Push Server
20
23. Server Push with Juggernaut
class MessengerController <
ApplicationController
def message
data = {:user => params[:user], :message =>
params[:message]}
message to socket
localhost:3000/
1. post to http://
3. push JSON
Nt
messenger/
O ke
message
JS soc
h
us to
. p age
Juggernaut.send_to_channel(data, :im_channel)
3s
es
m
render :nothing => true
end
2. send_to_channels
end
Juggernaut
Rails Application
Push Server
<mx:HTTPService id=quot;sendMessagequot; url=quot;http://
<net:XMLSocket id=quot;socketquot;
localhost:3000/messenger/messagequot;
connect=quot;connectHandler(event)quot;
method=quot;POSTquot; result=quot;msg.text=''quot;
data=quot;dataHandler(event)quot;
fault=quot;mx.controls.Alert.show(event.fault.faultS
close=quot;closeHandler(event)quot;
tring);quot;>
ioError=quot;ioErrorHandler(event)quot;
<mx:request xmlns=quot;quot;>
<user>{user.text}</user>
securityError=quot;securityErrorHandler(event)quot; />
<message>{msg.text}</message>
</mx:request>
socket.connect(hostName, port);
</mx:HTTPService>
24. File Upload
class Asset < ActiveRecord::Base
<net:FileReference id=quot;fileReferencequot; has_attachment :storage => :file_system
select=quot;selectHandler(event)quot; /> end
private function selectHandler(event:Event):void class AssetsController < ApplicationController
{ def create
var request:URLRequest = @asset = Asset.new(params[:asset])
new URLRequest(quot;http://localhost:3000/assetsquot;) if @asset.save
var uploadDataFieldName:String = render(:nothing => true, :status => 200)
'asset[uploaded_data]' else
fileReference.upload(request, render(:nothing => true, :status => 500)
uploadDataFieldName); end
} end
end
22