blog • WillianFernandes.com.br
Faye – Como eu criei um simples chat usando Rails
November de 8th de 2011 por Willian Fernandes
Recentemente precisei criar um chat para integrar com a aplicação da empresa que trabalho. Sim, mais um desenvolvimento de chat. Como dizem por ai, chat é o novo Hello World.
Já tinha ouvido falar do Faye, até o Ryan Bates fez um Railscasts sobre o assunto.
O Faye tem módulos para Ruby e Node.js.
Minha primeira tentativa foi utilizar a versão ruby do Faye. Essa versão nada mais é que uma aplicação Rack. Funcionou muito bem, até chegar em produção. O servidor que ele utiliza é o thin, e para a quantidade de requests que minha aplicação faz ao chat o servidor não durava 3 minutos em pé.
Depois de muito quebrar a cabeça resolvi partir para a versão em Node.js do Faye que resolveu perfeitamente esse problema. Vou mostrar abaixo como fiz para utilizando Faye, Node.js e Rails:
Primeiro você precisa ter o Node.js e o NPM instalados.
Na raiz da aplicação, instale o faye utilizando o npm:
$ npm install faye
Logo em seguida, também na raiz da aplicação, criei o arquivo abaixo:
faye_server.js
var http = require('http')
, faye = require('faye');
var Logger = {
incoming: function(message, callback) {
console.log('====================');
callback(message);
var bayeux = new faye.NodeAdapter({mount: '/faye', timeout: 60});
bayeux.addExtension(Logger);
bayeux.listen(9292);
Para testar se o faye está corretamente instalado e funcionando, rode o servidor:
$ node faye_server.js
E abra no seu nevegador a URL http://localhost:9292/faye.js. Se um arquivo JavaScript for carregar, então o Faye está funcionando corretamente. #WIN
No seu arquivo de layouts (ex.: application.html.erb) você precisa adicionar o JavaScript do Faye:
Agora basta criar uma instância para o Client do Faye e o canal que receberá as mensagens do nosso chat:
var faye_client = new Faye.Client('http://localhost:9292/faye');
faye_client.subscribe('/chat' , function(data) {
eval(data);
Criei um simples formulário que faz um POST para MessagesController::create utilizando AJAX:
<h1>Messages</h1>
<%= form_for @message, remote: true do |f| %>
<%= f.submit "Send" %>
E no controller MessagesController:
@message = Message.create(params[:message])
O segredo está na view app/views/messages/create.js.erb:
<% broadcast "/chat" do %>
$("#messages ol").append($("<li><%= @message.content %></li>"));
$("#message_content").val('');
Seguindo a dica do Ryan Bates, criei um helper para facilitar o envio das mensagens para o Faye Server. Ele será responsável em fazer o broadcast para todos os usuários conectados no chat.
def broadcast(channel, &block)
message = { channel: channel, data: capture(&block) }
uri     = URI.parse("http://localhost:9292/faye")
Net::HTTP.post_form(uri, message: message.to_json)
Como este helper está usando o Net::HTTP, precisamos adicioná-lo na nossa aplicação. Eu normalmente faço o require dessa lib no arquivo config/application.rb:
Com isso nosso chat está pronto!
Lógico que na minha aplicação existem processos um pouco mais complexos, lidando com chat privado (estilo Facebook) e autenticação de usuários. Mas para exemplo, esse caso mais simples vale.
Você pode baixar a aplicação completa diretamente do meu GitHub:
https://github.com/willian/faye_chat_example
Fácil, não!? Desabilitando Asset Pipeline no Rails 3.1
January de 31st de 2011 por Willian Fernandes
Fui convidado pelo Jésus Lopes (post) para falar um pouco sobre meu ambiente. Então segue abaixo o que eu uso no dia-a-dia. Macs
Desde fevereiro de 2008 trabalho exclusivamente com Mac OS X. No trabalho tenho um iMac Core 2 Duo 2.4 GHz com 4 GB de memória com Snow Leopard rodando.
Em casa uso meu bom e velho (ok, nem tão bom assim) MacBook preto, também com Snow Leopard mas com apenas 2 GB de memória. Editor
Quando trabalhava exclusivamente com Linux (Ubuntu) usava somente o Vim, mas nunca parei para realmente aprender a usá-lo. E quando migrei para o Mac conheci o TextMate e nunca mais troquei.
Com o mate me sinto em casa. Aprendi rapidamente seus atalhos, conheci e instalei alguns Bundles para me ajudar no dia-a-dia e sei que não preciso de mais nada para programar feliz.
Ainda uso o Vim para coisas nos servidores e de vez em quando para brincar e aprender um pouco mais sobre ele. Não, não pretendo trocar de editor. Mas pode ser que um dia precise e se precisar vou usar feliz da vida.
A freqüência com que uso o terminal é igual ou até mesmo maior do que com o TextMate. E nele fiz algumas configuração sugeridas pelo Nando Vieira. Meu .bashrc pode ser encontrado em meu GitHub.
Meu navegador padrão se tornou o Safari assim que adotei a plataforma Mac. Uso Chrome e Firefox apenas para desenvolvimento e olhe lá! Versionamento
Desde 2008 uso apenas o git para controlar meus projetos. SVN apenas quando preciso fazer checkout de algo.
Uso Ruby a maior parte do dia. Mas também não fico uma semana se quer sem brincar com JavaScript. Node.js tem me chamado muita atenção e JS está voltando a fazer cada vez mais parte dos meus desenvolvimentos.
Alfred: abandonei o QuickSilver faz alguns meses;
iTunes: ouço música o tempo todo;
Então agora convido @tinogomes e @lucashungaro para contarem do seus ambientes.
Depois de quase um ano usando o layout padrão do WordPress, resolvi criar um próprio e ver se assim me animo a escrever com mais frequencia por aqui.
Aproveitei para me aventurar um pouco no HTML 5 e CSS3 e provavelmente algumas coisas ainda quebrem em algum browser até que eu consiga ajeitar tudo por aqui.
Caso você esteja lendo esse post em um leitor de feeds, segue abaixo uma Screen shot de como ficou:
Tem alguma sugestão? Mande no comentário.
Testando Sinatra com RSpec (dica para quem usa Rails Metal)
June de 17th de 2010 por Willian Fernandes
Após ler o post do Diego Carrion sobre como usar RSpec para testar uma aplicação Sinatra, lembrei que tive um problema com os testes quando trouxe a aplicação feita em Sinatra para uma outra feita em Rails usando Rails Metal.
Vou usar o exemplo do Carrion para mostrar o que precisei mudar para os testes rodarem dentro do Rails Metal. Se no Sinatra usamos o spec_helper.rb assim:
require File.join(File.dirname(__FILE__), '..', 'main.rb')
No Rails Metal precisamos usar o arquivo spec_helper.rb normal, da forma como ele for gerado pelo RSpec.
A classe Api é um rails metal, mas nesse caso ela deve extender a classe Sinatra::Base (rails_root/app/metal/api.rb):
require(File.dirname(__FILE__) + '/../../config/environment') unless defined?(Rails)
E no arquivo api_spec.rb definimos o método app assim:
describe "Api" do
No exemplo acima precisei fazer require 'rack/test' no spec_helper.rb. Para isso, basta instalar a gem rack-test.
Como você pode ver, com uma simples mudança você pode usar Sinatra com Rails e fazer seus testes com RSpec.