Willian Fernandes

Faye – Como eu criei um simples chat usando Rails

Comente »

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:

Vamos ao código

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(message);
		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

Client-side

No seu arquivo de layouts (ex.: application.html.erb) você precisa adicionar o JavaScript do Faye:

<%= javascript_include_tag "http://localhost:9292/faye.js" %>

Agora basta criar uma instância para o Client do Faye e o canal que receberá as mensagens do nosso chat:
application.js

$(function() {
	var faye_client = new Faye.Client('http://localhost:9292/faye');
	faye_client.subscribe('/chat' , function(data) {
		eval(data);
	});
});
 

Back-end

Criei um simples formulário que faz um POST para MessagesController::create utilizando AJAX:
app/views/messages/index.html.erb

<h1>Messages</h1>
 
<div id="messages">
	<ol></ol>
</div>
 
<%= form_for @message, remote: true do |f| %>
	<%= f.label :content %>
	<%= f.text_field :content %>
	<%= f.submit "Send" %>
<% end %>
 

E no controller MessagesController:

class MessagesController < ApplicationController
  def index
    @message = Message.new
  end
 
  def create
    @message = Message.create(params[:message])
  end
end
 

Simples, certo?

O segredo está na view app/views/messages/create.js.erb:

<% broadcast "/chat" do %>
	$("#messages ol").append($("<li><%= @message.content %></li>"));
<% end %>
$("#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.

app/helpers/messages_helper.rb

module MessagesHelper
  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)
  end
end
 

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:

# ...
 
require 'rails/all'
require 'net/http'
 
# ...

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

Comente »

Se você é como eu e não gostou do assets pipeline que vem habilitado nativamente no rails 3.1, saiba que você pode desabilitá-lo. Para isso, basta editar o arquivo application.rb:

# Enable the asset pipeline
config.assets.enabled = false

Essa notícia não é nova, porém poucos sabem que ao desabilitar este recurso os arquivos controller_name.js e controller_name.css continuam sendo gerados no diretório app/assets/. Veja:

$ rails g controller users
  create  app/controllers/users_controller.rb
  invoke  erb
  create    app/views/users
  invoke  rspec
  create    spec/controllers/users_controller_spec.rb
  invoke  helper
  create    app/helpers/users_helper.rb
  invoke    rspec
  create      spec/helpers/users_helper_spec.rb
  invoke  assets
  invoke    js
  create      app/assets/javascripts/users.js
  invoke    css
  create      app/assets/stylesheets/users.css

Para evitar que isso aconteça basta fazer a configuração abaixo também no arquivo application.rb:

config.generators do |g|
  g.assets false
end

Com isso ao rodar o generator de controller teremos:

$ rails g controller users
  create  app/controllers/users_controller.rb
  invoke  erb
  create    app/views/users
  invoke  rspec
  create    spec/controllers/users_controller_spec.rb
  invoke  helper
  create    app/helpers/users_helper.rb
  invoke    rspec
  create      spec/helpers/users_helper_spec.rb

Fica então a dica.

RailsConf 2011

Comente »

Para quem não sabe dia 16 de maio acontecerá o RailsConf 2011. O evento será novamente em Baltimore e vai até o dia 19.

Eu nunca viajei para fora do país e minha primeira experiência será um tanto quanto interessante. Embarco dia 13 e chego dia 14, de madrugada, em Washington D.C, vou para Baltimore de carro no dia 15 e dia 20 volto para Washington onde fico até o dia 22. Dia 22 mesmo chego no Brasil.

Enfim, quero saber quem mais do Brasil estará por lá para marcar um #horaextra em Baltimore, ou em Washington.

Postarei no blog e no twitter a experiência de participar desse grande evento e de estar nos States.

Até lá!

Meu ambiente de desenvolvimento

Comente »

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.

Terminal

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.

Browser

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.

Linguagens de programação

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.

Outros programas

  1. Safari;
  2. Alfred: abandonei o QuickSilver faz alguns meses;
  3. iTunes: ouço música o tempo todo;
  4. YoruFukurou
  5. Keynote
  6. Pages
  7. Reeder
  8. TextMate
  9. Terminal
  10. iChat
  11. Dropbox
  12. MusicBrainz Picard
  13. Quicktime

Então agora convido @tinogomes e @lucashungaro para contarem do seus ambientes.

Novo layout

Comente »

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:
Novo layout

Tem alguma sugestão? Mande no comentário.

Até!

Testando Sinatra com RSpec (dica para quem usa Rails Metal)

Comente »

Após ler o post do Diego Carrion sobre como usar RSpec[bb] 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[bb] 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')
 
require 'spec'
require 'rack/test'
 
Spec::Runner.configure do |conf|
  conf.include Rack::Test::Methods
end
 
def app
  Sinatra::Application
end

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 'sinatra'
 
# Allow the metal piece to run in isolation
require(File.dirname(__FILE__) + '/../../config/environment') unless defined?(Rails)
 
class Api < Sinatra::Base
  # Code
end

E no arquivo api_spec.rb definimos o método app assim:

require 'spec_helper'
 
describe "Api" do
  include Rack::Test::Methods
 
  def app
    Api.new
  end
 
  # code
end

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.

Rails Summit 2009 – Eu vou!

Comente »

Estou aqui somente para comunicar minha presença no Rails Summit 2009.

Não preciso dizer o quanto estou ansioso para que esse dia chegue. Serão dois dias de muito conteúdo bom, de conhecimento garantido!

Nos vemos lá!

Rails Summit 2009

Rails Summit Latin America 2009 – Eu NÃO VOU (Por enquanto… hehehe)

Comente »

Dias 13 e 14 de outubro acontecerá o Rails Summit 2009. Um mega evento com muita gente boa falando sobre Rails, Agile, Escalabilidade, Testes (TDD, BDD, entre outros) e muitos outros assuntos relacionados ao framework.

Infelizmente não irei nesse ano, por motivos de força maior (casamento consumindo toda grana) não estarei presente no event. Quer dizer, não estarei presente até que eu ganhe o ingresso do sorteio de amanhã.

Boa sorte para mim e bom evento à todos!

Novo Servidor

Comente »

O blog esteve fora do ar por alguns minutos devido à mudança de servidor que fiz.

Estou usando o serviço de Cloud da Locaweb e por enquanto estou gostando.

Agora tudo deve voltar ao normal! ;)