Arquivo da tag: rubyamf

Flex + Rails com RubyAMF

Depois de demonstrar como utilizar o dapper.net para criar um serviço XML, chegou a hora de utilizarmos o serviço criado em um aplicativo. Quero demonstrar aqui o exemplo abaixo:

Dapper gera XML a partir do Y! Finanças, que é lido pelo Flex e, via RubyAMF, salvo no BD, através do Rails. Moleza.

O Dapper gera XML a partir do Y! Finanças, que é lido pela aplicação Flex e manipulado pelo usuário. Via RubyAMF, acessamos o controller no Rails, que salva os dados no BD.

E como tudo isso funciona junto?

Já vimos como extrair os dados do Yahoo! Finanças a partir do dapper, então vamos começar descobrindo como o Flex faz para acessar este serviço. Depois explicarei um pouco sobre o backend em Rails e como é feita a integração Flex + Rails através do RubyAMF.

Flex

O nosso exemplo aberto no Flex

O nosso exemplo aberto no Flex

Ao clicarmos em Obter cotação o sistema deve acessar o serviço XML e obter o valor da ação especificada no campo Símbolo. A função getStockInfo é encarregada desta operação. Ela é chamada no evento click do botão, recebe como parâmetro o valor do campo Símbolo e faz a chamada assíncrona ao serviço XML. O parâmetro noCacheControlVar é adicionado a cada nova requisição ao serviço, para que uma nova URL seja criada e o resultado da requisição não seja cacheado no browser.

private function getStockInfo(stockCode : String) : void{
cursorManager.setBusyCursor();
var timeStampForNocache:Date = new Date() ;
var params : Object = new Object();
params.v = 1;
params.v_StockCode = stockCode;
params.noCacheControlVar = timeStampForNocache.getTime().toString();
httpStockQuoteProvider.send(params);
}

O Flex acessa serviços XML através do componente <mx:HTTPService>. Neste exemplo, vamos configurá-lo para acessar a URL http://www.dapper.net/RunDapp?dappName=Bovespa, que é a URL que contém o serviço XML que desejamos acessar.

<mx:HTTPService id="httpStockQuoteProvider" method="GET" url="http://www.dapper.net/RunDapp?dappName=Bovespa"
resultFormat="e4x"
result="httpResultHandler(event)"
fault="httpFaultHandler(event)"
showBusyCursor="true" />

O trecho de código acima nos diz muita coisa sobre o funcionamento do HTTPService. O serviço httpStockQuoteProvider irá acessar a URL informada utilizando o método GET do protocolo HTTP. O resultado – que sabemos ser em XML – será tratado pelo E4X, que é uma biblioteca de acesso nativo ao XML. Quando o serviço entrar em ação, o cursor irá mudar para uma ampulheta, pois setamos a propriedade showBusyCursor como true, e os eventos em caso de sucesso ou falha serão tratados pelas funções httpResultHandler e httpFaultHandler, respectivamente. Estas funções são responsáveis por fazer o tratamento da resposta do serviço:

private function httpResultHandler(event : ResultEvent) : void{
var dapper : XMLList = (event.result as XML).dapper;
var Quote_Details : XMLList = (event.result as XML).StockQuote;
if (dapper.status == 'OK') {
xmlStockQuoteData = Quote_Details;
txtValue.text = parseFloat(xmlStockQuoteData.Price).toString();
}else if (dapper.status == 'ERROR'){
Alert.show(dapper.description, 'Error code ' + dapper.errorCode)
}
cursorManager.removeBusyCursor();
}

A função httpResultHandler recebe o resultado do evento e popula a variável xmlStockQuoteData com os dados recebidos do XML. A variável dapper recebe os dados do nó dapper do XML e verifica o elemento status, que traz o status do serviço.

private function httpFaultHandler(event : FaultEvent) : void{
Alert.show(event.fault.message, 'HTTP Service Error');
cursorManager.removeBusyCursor();
}

A função httpFaultHandler mostra um alerta caso ocorra uma falha na conexão HTTP.

Com isso já conseguimos obter os dados do serviço XML. Mas, para tornarmos o exemplo um pouco mais prático, temos que poder manipular estes dados de alguma forma e salvá-los no banco de dados. É aí que entra o Rails, juntamente com o RubyAMF.

RubyAMF

Antes de entrar em maiores detalhes, vou explicar o que é o RubyAMF e como instalá-lo no Rails.

O RubyAMF é um gateway para comunicação entre o Flex (ou Flash) e o Rails. Ele é instalado no Rails e permite que os métodos dos controllers sejam acessados remotamente via AMF, que é um formato binário de comunicação de dados.

Instalação

O comando abaixo instala a última versão do RubyAMF.

$ script/plugin install http://rubyamf.googlecode.com/svn/current/rubyamf

Configuração

Em config/rubyamf_config.rb (que é gerado automaticamente na instalação)

ClassMappings.translate_case = true
ClassMappings.assume_types = true
ParameterMappings.scaffolding = true

translate_case: mapeia convenções de código – created_at (Rails) e createdAt (Flex).
assume_types: assume que a classe do objeto é a mesma classe remota no Flex (devem ter o mesmo nome). Pode acarretar em perda de performance quando setado como true. Pode ser substituído por ClassMappings.Register(…).
scaffolding: permite parâmetros nomeados (de params[0] para params[:stock_quote]).

Quando assume_types é false devemos utilizar ClassMappings.Register para o mapeamento entre as classes do ActionScript e do Rails:

ClassMappings.register(
:actionscript => ‘StockQuotes’,
:ruby => ‘StockQuotes’,
:type => ‘active_record’,
:attributes => [“id”, …])

Para maiores detalhes sobre estas configurações, recomendo a leitura da apresentação feita pelos criadores do RubyAMF.

Rails com RubyAMF

Scaffolding

O rubyamf_scaffold gera model, fixtures, migrations e um controller com as operações de CRUD já implementadas. Ele não gera views, pois não serão necessárias.

$ script/generate rubyamf_scaffold StockQuotes name:string value:float

Migrations

$ rake db:migrate

No Rails é só isso que precisamos fazer. Agora voltaremos ao Flex para descobrir como é feita a integração com o Rails via RubyAMF.

Flex com RubyAMF

Primeiramente, precisamos criar uma classe StockQuotes em ActionScript que reflita as propriedades da classe StockQuotes do Rails, da seguinte forma:

package
{
[RemoteClass(alias="StockQuotes")]
public class StockQuotes
{
public var id:int;
public var name:String;
public var value:Number;
public var createdAt:Date;
public var updatedAt:Date;
public function StockQuotes()
{
}
}
}

Note como marcamos a classe StockQuotes como remota com a diretiva [RemoteClass(alias="StockQuotes")]. Isto é necessário para o mapeamento de objetos remotos.

O Flex acessará o gateway criado pelo RubyAMF através do componente <mx:RemoteObject>. O RemoteObject, como o próprio nome já diz, é um componente para acesso a dados remotos. No nosso exemplo, nós o configuramos da seguinte maneira:

<mx:RemoteObject id="amfService"
destination="rubyamf"
endpoint="http://localhost:3000/rubyamf_gateway/"
source="StockQuotesController"
showBusyCursor="true"
fault="amfFaultHandler(event)" />

Veja que como endpoint nós configuramos a URL http://localhost:3000/rubyamf_gateway/, que é a URL padrao do gateway do RubyAMF. Na propriedade source setamos StockQuotesController, que é o nome do nosso controller no Rails. Desta forma o Flex conseguirá acessar os métodos deste controller para realizar as operações desejadas. A função amfFaultHandler cuidará do tratamento de erros em caso de falha na conexão.

Agora, para nos comunicarmos com o Rails via RubyAMF basta criarmos funções que façam chamadas aos métodos do controller:

private function findAll():void {
amfService.removeEventListener(ResultEvent.RESULT, saveResultHandler);
amfService.addEventListener(ResultEvent.RESULT, findAllResultHandler);
var call:AsyncToken = amfService.find_all();
}

A função findAll traz a lista de todos os dados que estão salvos no banco. Note como ela chama o método correspondente find_all do StockQuotesController. O resultado desta chamada assíncrona é tratado pela função findAllResultHandler, que mostra os dados obtidos em um grid.

Também temos funções que fazem mapeiam o Save, Update e Destroy, correspondendo à todas as funcionalidades de um CRUD simples, que é o propósito deste exemplo. Para baixar o código-fonte completo desta aplicação, acesse a sessão de downloads abaixo. Sinta-se à vontade para fazer modificações no código ou enviar sugestões e dúvidas através dos comentários.

Downloads

8 Comentários

Arquivado em Artigos