jQuery, Ajax, e Rails

2010-05-14

Para além das lides habituais com o desenvolvimento em ASP.Net com C# e  muito Javascript, tenho tido nas últimas semanas oportunidades para trabalhar com Ruby on Rails. É uma linguagem e framework bastante interessante, sem dúvida, e uma abordagem diferente à construção de páginas, visto que aplica o padrão MVC.

Ainda estou a aprender muito do muito básico, mas tenho conseguido com alguma comunicação com os colegas, aplicar conceitos que já aplicava no .Net, especialmente no que diz respeito ao uso de javascript no browser e a troca de dados por Ajax.

Em termos de Ajax, tenho-me concentrado essencialmente em usar o jQuery para efectuar os pedidos e manipular os dados. Muito raramente (mais para o nunca), uso os controlos da biblioteca de Ajax da MS. não é que sejam menos bons, simplesmente gosto de usar o jQuery e construir de baixo para cima os componentes. Por vezes os truques escondidos dos controlos estragam a experiência de desenvolvimento. Aprendi isso com os controlos da DevExpress…

Com jQuery, o pedido por Ajax é realizado simplesmente usando o $.ajax() , com as opções devidamente preenchidas. Até já tinah construido uma função numa biblioteca “core” pessoal para abstrair alguns detalhes como a definição de JSON como formato de pedido e resposta:

Asp.Net Way

O GetAjaxData é apenas um género de wrapper em torno do $.ajax(), fixando alguns parâmetros e aplicado os argumentos como os dados a transmitir, o caminho e nome do método a executar, e os callbacks. Por exemplo, se tiver um método de página (gosto de usar assim) que deva chamar, teria algo do género:

O método apresentado é algo ridículo, mas serve para explicar. Temos um método da classe da página (supomos “QQPagina.aspx”), que se chama “MetodoAChamar”, recebe um parâmetro inteiro “id” e devolve um inteiro. É importante notar que o método é static (portanto ao nível da classe e não instanciado – não que acesso às propriedades instanciadas da classe). Também, apesar de usar aqui um método numa página Aspx, podia ter colocado o mesmo numa classe de WebService. Ambos os métodos teriam o atributo “[WebMethod]”, mas o método no WebService não é static.

Para executar o método, podia fazer algo do género:

A função no JavaScript ChamarMétodo efectua o pedido Ajax, e apresenta o resultado num alerta.reparem que os dados são preparados no argumento DTO e devidamente formatado em JSON. O endereço da página é relativa à actual.

Se tudo estiver OK, o resultado seria uma caixa de mensagem a aparecer com 5000 escrito e um botão de OK.na verdade, o retorno pode ser objectos complexo (devolvidos estruturados em JSON) para depois construir parte da interface, o HTML directo para reconstruir uma parte da página. É de lembrar que os dados retornados são encapsulados numa propriedade base do resultado que é o “d”.

O que gosto deste método é o facto de poder usar um código mais limpo no cliente, e mais controlo sobre o momento e operações de pedidos.

Ruby on Rails Way

Para Ruby On Rails (RoR), há uma serie de formas de conseguir, e a framework tem uma integração interessante com o Prototype. Pessoalmente estou treinado no jQuery, e portanto procurei formas de conseguir usar este.

A maior dificuldade que encontrei foi perceber o mecanismo da chamada, já que o uso do padrão MVC supõe algumas considerações. O endereço à qual é efectuado o pedido deve ter em conta o esquema de routing, por exemplo, e é necessário ter atenção à forma como é renderizado o layout – não deve ser renderizado normalmente, visto que só queremos transmitir uma pequena porção de HTML ou os dados para o construir.

Começando pelo função de JavaScript que chama o método do controlador, mantém-se praticamente idêntico, excepto que, devido à aplicação do routing, é conveniente escrever o endereço e o método de uma só vez. O rails até ajuda nesse aspecto:

Tem outro nome neste momento, e menos um parâmetro, e pode ser introduzido numa biblioteca de funções base. O Rails permite injectar código para chamar código remoto, usando blocos como o “link_to_remote” ou o “forms_remote_tag”. Neste caso, na View, vou introduzir o código entre tags de script explicitamente, em vez de depender do Rails para o gerar:

É em muito semelhante ao ChamarMetodo() que usamos no exemplo para o .Net, mas neste caso é o rails a dar-nos o endereço do URL a que faremos o pedido usando o “<%= url_for(:action => ‘doAjaxOperation’) %>”, onde doAjaxOperation é o nome do método a executar no controlador. Assim, no Controlador, devemos ter:

Assim ‘doAjaxOperation’ é um método da classe do controlador actual (deve ser publico!) e porque tem o “render(:json …) ou o render :text, o método irá ignorar o layout, evitando reconstruir toda a página, e apenas lançar aquilo que necessitamos (que neste caso seria “Olá Miguel Alho, 1”). outra opção para não renderizar o layout seria utilizar “render :layout => false” dentro do método.

Os argumentos que enviamos, vão no POST da mensagem (é interessante ver isto no FireBug!), e para os decifrar, usamos ActiveSupport::JSON.decode(request.raw_post()). postData passa a ter o objecto nele e podemos ter acesso as propriedades do POST enviadas no pedido.

No fim, deve ser tido em conta que, ao contrario do .Net, os dados da resposta são entregues directamente no argumento da função do sucesso, e não encapsulados numa propriedade “d”. Portanto, em vez de termos um “msg.d” com a string “Olá Miguel Alho, 1”, o próprio msg teria essa informação.

Para mim, a transição não foi de todo fácil ,mas confesso que não tenho ainda boas bases nem do Ruby, nem do Rails, para facilitar. Felizmente, com o conhecimento adquirido no .Net com esta matéria, foi pelo menos ter uma boa base de arranque e encontrar o caminho.Espero que esta informação possa ajudar alguém!