Rails Summit 2009: Estive lá

rails_summit_09_entrada

Eu, Ricardo e Chad

A Viajem

Foi cansativo, mas mais uma vez valeu muito a pena. Desta vez não conseguimos interessados suficientes para organizar uma caravana paranaeense, então nos aventuramos eu e o RicardoK a viajar de Londrina até São Paulo de ônibus. A viajem corria bem, até percebermos que era volta de feriado prolongado e que enfrentaríamos mais de 100km de trânsito lento. Chegamos com mais de 3 horas de atraso, mas ainda assim com muito tempo para descansar antes do evento. Fiquei no mesmo hotel do ano passado, perto do metrô tietê, onde havia combinado de dividir o quarto com o Leonardo Faria, programador de Divinópolis-MG que até então não conhecia pessoalmente.

O Evento

rails_summit_09_vinicius

Eu e Vinicius Teles

A RailsSummit 2009 aconteceu nos dias 13 e 14 de outubro, no Centro de Convenções Anhembi. Foi a segunda edição do maior evento sobre o tema na América Latina. Estive presente também na primeira edição, que foi bem organizada e teve um valor especial para mim, pois foi onde consegui meu emprego atual. Devido a isso, já tínhamos uma expectativa muito boa para a edição desse ano, só não acreditava que seria possível um evento melhor que o do ano passado. Mas foi…

Neste ano não só corrigiram alguns poucos problemas que haviam ocorrido, como melhorar a temperatura do auditório B, como também aumentaram o espaço para networking e o espaço do restaurante, melhoraram o acesso à internet e acrescentaram tradução das palestras de português para para inglês. Além disso, como em um bom evento geek, tivemos um espaço com video-games, onde pude derrotar meu padrão no boxe do Wii =).

Quanto às palestras, mais uma vez tivemos temas variados abordados por grandes nomes internacionais e nacionais, que foram de escalabilidade e testes até empreendedorismo. O Leonardo fez um resumo do primeiro e do segundo dias. Foram muitas apresentações excelentes, com destaque para Gregg Pollack mostrando várias gems e plugins para ajudar na melhora da performance das aplicações no primeiro dia e para Vinicius Teles, falando sobre suas experiencias de empreendedorismo com a ImproveIt, e Obie Fernandez, que falou sobre a arte de desenvolver aplicações, já no segundo dia.

Encontros

rails_summit_09

Jony, Herval, Leozera, Eu e RicardoK

Participar de um grande evento como foi o Rails Summit também é uma ótima oportunidade para rever amigos que moram em outras cidades ou estados, e ainda para conhecer aqueles desenvolvedores que você só reconhece o avatar das redes sociais, twitter e IMs. Reencontrei o pessoal do paraná (Ozéias, Davis, Zé Gomes, Maurício) e de outros estados (Thiago Freire, Jony), e também conheci alguns railers pessoalmente pela primeira vez (Leonardo Faria, Herval, Roberto Soares, Diego e George Guimarães).

Tive a chance de conhecer também alguns participantes do rails-hits podcast, como o Elomar França e o Paulo Fagiani, que já estavam promovendo o Oxente Rails 2010, e o Vinícius Teles, que fez uma das palestras mais motivadoras da conferência.

E ainda, como na edição passado, o Chad estava presente, desta vez com mais alguns desenvolvedores vindos de Buenos Aires. É sempre bom poder conversar sem usar o skype, que é como fazemos diariamente no trabalho para a Reach.

Conclusão

Sem dúvidas, o que fica do evento é um saldo muito positivo. Algumas sugestões que fizemos no ano passado foram implementadas, como o uso do login no crachá do evento. Já as camisetas, para mim acabaram sendo um grande #fail. Deixo aqui os parabéns ao Akita e a Locaweb pela organização, aos patrocinadores do evento, e aos Railers de todos os cantos do Brasil e alguns de fora dele, que compareceram e fizeram uma conferência ainda melhor que a anterior. A comunidade parece estar crescendo e mais do que isso, está amadurecendo, com cada vez mais profissionais trabalhando e contribuindo com a tecnologia. Volto para a rotina de trabalho com a motivação renovada.

* Algumas fotos do flickr da locaweb, veja outras fotos do evento também no meu flickr.

Filter Table: Plugin para geração de filtros para Rails

Filter Table é um plugin para Ruby on Rails que possibilita uma forma simples para filtragem de dados. O plugin adiciona um método ao controller para gerar condições do ActiveRecord baseado nos parâmetros passados na requisição. Além disso, o plugin inclui Helpers para auxiliar a inserção dos links de filtros nas Views.

Instalando:

O código do plugin está hospedado no GitHub, para instalá-lo em sua aplicação, execute o comando:

script/plugin install git://github.com/flaviogranero/filter_table.git

Usando:

Para usar o plugin, basta adicionar uma chamada ao método filter_attributes no controller desejado, passando os atributos que podem ser usados na construção do filtro. Feito isso, pode-se chamar o método filter_conditions na carga de dados do seu modelo. Vejamos um exemplo de uso no controller:

Controller (cars_controller.rb):

class CarsController < ApplicationController
    filter_attributes :status

    def index
      @cars = Car.paginate :page => params[:page], :conditions => filter_conditions
    end
  end

Observe que o modelo Car possui um atributo “status” do tipo inteiro, que será usado pelo plugin para gerar as condições baseado nos valores passados como parâmetros da requisição. Um exemplo de URL filtrando os carros com status igual a 1 por exemplo, seria: /cars?status=1

Os filtros ainda podem ser combinados. Um exemplo para isso seria uma requisição para mostrar os carros com status igual a 1 OU a 2: /cars?status=1+2

Criar links na sua página de listagem com todas as combinações de filtros pode ser um tanto trabalhoso. Para facilitar isso, o plugin conta com método auxiliar com essa finalidade, chamado filter_links_for. Os parâmetros para o método variam de acordo com a necessidade e o tipo do atributo. Vejamos algums exemplos de views.

View (index.html.erb):

<h1>Cars</h1>
  <div>
    <h2>Filters</h2>
    < %= filter_links_for :status, :values => {'Normal' => 0, 'Broken' => 1, 'Running away' => 2} %>
  </div>
  <table>
    <tr>
      <th>Name</th>
      <th>Status</th>
      <th>Category</th>
    </tr>
    < % @cars.each do |car| %>
      <tr>
        <td>< %=h car.name %></td>
        <td>< %= car.status %></td>
        <td>< %= car.category %></td>
      </tr>
    < % end %>
  </table>

No exemplo de view acima, temos como parâmetro o atributo status, e um Hash com os captions e valores possíveis na chave :values.

Você pode ainda passar alguns parâmetros opcionais, como o título da lista de links que será gerada, usando a chave :title, e a classe css usada em filtros ativos pela chave :active_class, cujo valor padrão é “filter_active”.

O parâmetro :values aceita Hashs, Arrays ou ainda o valor :auto. Neste último caso, os links dos filtros são geradas a partir de uma query no banco de dados por valores distintos do atributo em questão. Para que isso seja possível, é necessário o uso da chave :model associada ao nome do Modelo, como pode ser observado no exemplo abaixo, para o atributo category:

View (index.html.erb):

<h1>Cars</h1>
  <div>
    <h2>Filters</h2>
    < %= filter_links_for :status, :values => {'Normal' => 0, 'Broken' => 1, 'Running away' => 2} %>
    < %= filter_links_for :category, :values => :auto, :model => 'Car' %>
  </div>
  <table>
    <tr>
      <th>Name</th>
      <th>Status</th>
      <th>Category</th>
    </tr>
    < % @cars.each do |car| %>
      <tr>
        <td>< %=h car.name %></td>
        <td>< %= car.status %></td>
        <td>< %= car.category %></td>
      </tr>
    < % end %>
  </table>

Para cada valor de filtro, é gerado um link para filtragem exclusiva, e outro para adicionar o valor ao filtro atual. Quando um filtro já está aplicado, esse link é substituído por outro, com a função de remover o valor do filtro atual.

Contribuindo:

Contribuições com idéias e novas funcionalidades são sempre bem vindas. O plugin possui cobertura por testes unitários, bastando executar “Rake test” dentro de sua pasta. Fique ä vontade para clonar o repositório em

http://github.com/flaviogranero/filter_table/

Conclusão:

O uso do plugin filter_table torna páginas com grandes listas de dados, principalmente as usadas para administração de sistemas, mais fáceis de navegar e de visualizar.

Criei o plugin para sanar a necessidade por filtros que tinha em páginas administrativas de um sistema em Ruby on Rails, já que as soluções em plugins e gems existentes com a solução são normalmente complexos de configurar e manter, agregam muitas funcionalidades e na maioria das vezes fazem uso de AJAX de forma abusiva.

O filter_table destina-se a resolver apenas o problema dos filtros, sem mágica, mantendo o código simples.

Ilustrações: Camisetas de Carnaval

Criar a ilustração da camiseta do bloco de carnaval “Os Macabros” tem sido uma tarefa muito legal, apesar de ser apenas uma vez por ano. O bloco surgiu em 1998 e participa do carnaval da minha cidade natal (Kaloré) até hoje. Eu não fiz a primeira ilustração, mas fiz praticamente todas as outras.

Infelizmente, foi apenas nos últimos anos que passei a ilustrar usando softwares vetoriais. Antes usava apenas a velha combinação de lápis e papel, talvez por isso não tenha mais os desenhos originais, ou eles devem estar perdidos em alguma gaveta.

Fazer esse tipo de desenho é uma ótima oportunidade para exercitar a criatividade e tentar melhorar o traço, já que não tenho reservado tempo para outras ilustrações. Na sequência a seguir, os desenhos da frente e das costas das camisetas, de 2006 até 2009.

2006

Macabros_frente_2006Macabros_frente_2006

2007

Macabros_frente_2007macabros_costas_2007

2008

Macabros08_FrenteMacabros_Costas_2008

2009

macabros_frente_2009macabros_costas_2009

Ruby Gem: Escopo de busca fácil no ActiveRecord

Escrevi a algum tempo um post mostrando como usar campos FULL TEXT do MySQL para ter uma sistema de busca simples mas eficiente em suas aplicações Rails. Para quem não precisa de uma busca mais sofisticada, o plugin acts_as_fulltextable quebra o galho. 

Porém, recentemente me deparei com um situação onde precisava de algo ainda mais simples. Para um sistema de administração de conteúdo, a busca devia pesquisar apenas em um Model, e em apenas alguns campos. Portanto criar uma tabela extra no banco de dados, como o acts_as_fulltextable faz, seria um pouco dispendioso. 

Uma solução simples seria usar o método Model.find_by_name por exemplo, para buscar um registro pelo campo ‘name’, mas isso traria apenas um registro e sem a possibilidade de buscar por mais de um campo com uma única execução. Outra solução seria a criação de named_scopes, mas seria um tanto trabalhoso filtrar por vários atributos e ainda tratar a entrada de dados.

Foi então que encontrei a gem scoped_search. Quando instalada, ela adiciona um escopo para buscas em models do Active Record chamada search_for, a qual usa cláusulas LIKE da linguagem SQL para efetuar filtros, diretamente no banco de dados.

Instalação:

Adicione ao environment.rb de sua aplicação:

config.gem 'wvanbergen-scoped_search', 

           :lib => 'scoped_search', 

           :source => 'http://gems.github.com'

Depois, execute o comando:

$ rake gems:install

 

Utilização:

Basta adicionar uma linha no Model desejado, indicando os campos que serão usados na busca:

class User < ActiveRecord::Base

  searchable_on :login, :name

end

Depois da alteração, a classe passa a contar com o escopo search_for, que pode ser usado em cascata com outros named_scopes. No exemplo abaixo de uma action “search” do controller de usuários, integra-se a busca com a paginação provida pelo will_paginate:

 def search

   @users = User.search_for(params[:q]).paginate(:page => params[:page])

    respond_to do |format|

     format.html 

     format.xml  { render :x ml => @users }

   end

 end

Bem tranquilo. Para incrementar um pouco, podemos ainda adicionar campos de associações na busca. Supondo que o usuário tenha um perfil (profile), podemos adicionar o campo description pertencente ao perfil na busca, da seguinte maneira:

class User < ActiveRecord::Base

  has_one :profile, :dependent => :destroy

  searchable_on :login, :name, :profile_description

end

 

 
No MySQL, pode-se ainda utilizar índices FULLTEXT nos campos mais requisitados, para aumentar a performance das buscas.

FonteEasy search with ActiveRecord

Rails Summit: Emprego Novo!

Você pode estar pensando:

Mais um post sobre a Rails Summit? Não está um pouco atrasado não?

Atrasado, pode ser, mas foi porque estava esperando um bom momento para publicá-lo.

Foram 5 anos de desenvolvimento Delphi, onde eu tive o prazer de trabalhar com uma equipe muito competente e inovadora. Os desenvolvedores Delphi são normalmente taxados como “pregadores de botão”, por desenvolvedores de outras linguagens. Mas no caso da nossa equipe isso não acontecia. Com foco no desenvolvimento de ferramentas e frameworks, estávamos sempre buscando e aplicando práticas modernas de desenvolvimento e gerenciamento. E foi esse ambiente que me prendeu por esse tempo.

Mas agora chega a hora de novos desafios. Venho usando Ruby on Rails já há mais de 2 anos, apenas em projetos pessoais, desenvolvidos em meu tempo livre. A tecnologia me chamou tanto a atenção que passei a usá-la em aplicações, a escrever textos esporádicos aqui no blog, a participar da comunidade, me preparando para conseguir uma oportunidade de usá-la em tempo integral.

A oportunidade apareceu justamente durante a Rails Summit. Confesso que quando me inscrevi para o evento, eu sabia que essa seria uma ótima chance de conhecer de perto outros desenvolvedores e buscar oportunidades. Muito se falou sobre o evento, foram muitos posts, fotos e twitts destacando a qualidade das palestras e da organização, o que é realmente indiscutível e não pretendo ser repetitivo aqui. Mas além de tudo isso, para mim o evento teve essa outra face. Durante um dos intervalos entre as palestras, estava conversando com o pessoal da caravana paranaense e conhecemos Chad DePue, um americano residente em Buenos Aires que estava participando do evento e a procura de railers para trabalho remoto. Eu, logicamente, me candidatei =D.

Chad DePue na Rails Summit

Chad DePue na Rails Summit (foto por tapajos)

Depois do evento, tivemos algumas conversas e testes e agora posso dizer que sou o mais novo desenvolvedor da Reach Network, empresa sediada em Seattle, a qual o Chad presta serviços através da sua consultoria, a Inaka Networks.

Estou muito satisfeito em começar essa nova fase na minha carreira e gostaria de agradecer a toda a comunidade Rails que é muito receptiva e prestativa, especialmente aos Railers do paraná que conheci melhor durante o evento e ao Fábio Akita, por organizar um evento de tão alto nível como foi a Rails Summit. Além desses, uma figura importantíssima nesta mudança foi o Ozéias do RailsBox, que organizou muito bem a caravana paranaense e me deu várias dicas sobre trabalho remoto, valeu cara! 

Caravana paranaense (com alguns catarinenses também)

O evento superou as minhas expectativas, mas como sugestão para o próximo, espero que possamos ter avatares nos crachás e camisetas nerds para comprar =D

Valeu galera e até o próximo evento.

SEO on Rails: URLs Amigáveis

Deixar as URLs de sua aplicação amigáveis pode fazer uma grande diferença no ranking dos mecanismos de busca. Isso significa fazer com as URLs fiquem mais simples, criando endereços que sejam legíveis e que tragam alguma informação sobre o conteúdo da página.

Vejamos alguns exemplos de URLs complexas:

index.php?section=cine&category=comedy

ou

/cgi-bin/index.cgi?id=6F7YCH&page=6

Quais os problemas de ter URLs complexas?

  • A complexidade da URL torna o endereço difícil de memorizar
  • Em alguns casos fica difícil de saber o que você vai encontrar antes de clicar em um link desse tipo
  • A tecnologia utilizada pelo aplicativo fica exposta
  • Se a tecnologia utilizada no site tiver que ser alterada (php para ruby, por exemplo), todas as URLs antigas ficarão inválidas

A solução com Rails

Para quem usa Rails, principalmente da maneira Restful, já tem esses problemas minimizados. Basta fazer um scafold e as URLs para as actions já ficam em um formato simples, como no nosso exemplo de locadora abaixo:

Lista de filmes

http://locadora.com/filmes

Detalhes de um filme com id igual a 12

http://locadora.com/filmes/12

Novo filme

http://locadora.com/filmes/new

Edição de um filme com id igual a 12

http://locadora.com/filmes/12/edit

 

Esse é um dos conceitos de REST: a URL deve descrever o recurso disponibilizado. Acha que está bom? Está, mas podemos melhorar ainda mais. Não seria melhor se ao invés de identificadores numéricos, tivéssemos o próprio título do filme na URL? Por exemplo, a página com detalhes do filme teria a endereço:

http://locadora.com/filmes/de-volta-para-o-futuro

Existem algumas maneiras de fazer isso em um aplicação Rails. Uma bem simples é instalando o plugin permalink_fu:

$ script/plugin install git://github.com/cyu/permalink_fu 

Depois de instalado, basta fazer a seguinte chamada nosso Model Filme, para usar o campo título como identificador na URL:

  class Filme < ActiveRecord::Base

    has_permalink :titulo

  end

Logicamente o campo título terá seus caracteres especiais e espaços removidos para poder ser usado como endereço http.

Essa abordagem só é viável quando o título do filme é único, pois ficaria impossível distinguir entre dois filmes com o mesmo título, já que ambos teriam a mesma URL. Para estes casos, podemos sobrescrever o método to_params, usando o helper PermalinkFu.escape do plugin para remover acentos e espaços do campo que queremos usar na composição do endereço: 

class Filme < ActiveRecord::Base

  def to_param

    "#{id}-#{PermalinkFu.escape(titulo)}"

  end

end

Assim, teríamos o formato:

http://locadora.com/filmes/12-de-volta-para-o-futuro

Essa solução causa um pequeno efeito colateral, já que o parâmetro recebido pelo controller em params[:id] não terá apenas um valor do tipo inteiro, mas sim uma string. Observe o exemplo de método show do controller de filmes: 

class FilmesController < ApplicationController

  def show
   @filmes = Filme.find(params[:id].to_i)

   respond_to do |format|
     format.html # show.rhtml
     format.xml  { render :x ml => @filmes.to_xml }
   end

  end
end

Note que é necessário uma conversão do paramêtro ID para o tipo inteiro, em params[:id].to_i, para que o find funcione corretamente.

O uso de URLs amigáveis, além de deixar os endereços de sua aplicação mais fáceis de entender e de lembrar, também fazem com que o posicionamento nos buscadores melhore, já que palavras chave pesquisadas passam a aparecer também nos seus links. 

Leia mais sobre o uso de URLs amigáveis:

Criando URLs amigáveis em brunotorres.net

Better Search Engine Friendly URL’s with Ruby on Rails

SEO Optimization of URLs in Rails with to_param

SEO on Rails: Títulos e Meta-Tags

Otimizar um site para que ele seja bem posicionado pelos mecanismos de busca é uma preocupação recorrente a maioria os desenvolvedores web. As chamadas técnicas de SEO já não são segredo e existem muitos bons sites que ensinam como alcançar as primeiras páginas do Google. Logicamente apenas o próprio Google pode garantir uma posição em seu resultado, mas existem alguns fatores que quando levados em consideração influenciam diretamente esse posicionamento.

Quando criamos um sistema usando Rails, alguns pontos podem passar desapercebidos, devido as convenções usadas pelo framework. Pretendo iniciar uma série de posts mostrando como fazer SEO em aplicações Rails, mostrando alguns métodos e plugins que podem facilitar o nosso trabalho.

Técnicas de SEO

Para ter uma introdução sobre o que significa SEO e como são classificadas essas práticas, principalmente pelos mecanismos de busca, eu recomendo a leitura do artigo White, Gray e Black Hats. Neste post do tableless, Diego Eis mostra exemplos de técnicas White Hat, que são as recomendadas pelos buscadores, as técnicas Gray Hat, que se utilizadas se forma abusiva são consideradas anti-éticas, e ainda das Black Hat, essas sim tomadas como forma de enganar o ranking, e que quando descobertas são punidas com a remoção do site infrator.

As boas práticas recomendadas (White Hat) podem ser resumidas em: criar bom conteúdo e criar links internos. Para os buscadores, um bom conteúdo é um conteúdo relevante, ou seja, um conteúdo que por sua qualidade está sendo linkado por editores de outros sites. Além da qualidade, atualmente os buscadores verificam se esse conteúdo está formatado adequadamente, fazendo uso correto de meta-tags e estrturado de acordo com as definições da W3C. O Google, por exemplo, classifica melhor páginas bem formadas, com tags semanticamente corretas e uma boa hierarquia de títulos. Uma boa dica é sempre utilizar a ferramenta validação de HTML e CSS da W3C e ainda as ferramentas para webmasters disponibilizadas pelo próprio Google, que verificam diversos aspectos que alteram a indexação.

Títulos e Meta-Tags

Quem já teve um site indexado sabe da importância dada à tag com o título da página (<title>) e as chamadas meta-tags, com a descrição (<description>) e as palavras chaves (<keywords>), que vão no cabeçalho do HTML. Por isso, é importante que cada página da sua aplicação tenha conteúdos distintos nestas tags, algo que se encaixe com o conteúdo apresentado. Para facilitar esse trabalho, vou apresentar o plugin para Rails chamado meta-tags.

Se você tem o GIT instalado, vá até a pasta da sua aplicação e execute:

$ script/plugin install git://github.com/kpumuk/meta-tags.git

Feito isso, você já pode organizar melhor o conteúdo de suas meta-tags. Vejamos como utilizar o plugin em uma aplicação Rails, que para fins de exemplo, chamarei de “Locadora”.

No layout da aplicação (normalmente em app/views/layouts/application.html.erb), use o helper display_meta_tags, da seguinte maneira:

  <head>

    < %= display_meta_tags :site => 'Locadora' %>

  </head>

Este método é responsável por inserir as tags e title, description e keywords no HTML. Depois, podemos configurar valores como o título da página para cada view, usando a seguinte chamada:

  
<h1>< %= title 'Locações pendentes' %></h1>

Fazendo isso por exemplo, quando a página acima for mostrada, sua tag title será configurada de acordo com o conteúdo, no formato abaixo:

  <head>

    <title>Locadora | Locações pendentes</title>

  </head>

  <body>

    
<h1>Locações pendentes</h1>
  </body>
É possível ainda setar o valor das tags diretamente dos controllers, acessando variáveis de instância:
@page_title = 'Locações pendentes'
@page_description = 'Lista de locações que ainda não foram devolvidas.'
@page_keywords = 'Locadora, Locações, Pendentes'

Ou ainda, usando o método set_meta_tags:

set_meta_tags :title => 'Locações pendentes',
                     :description => 'Lista de locações que ainda não foram devolvidas.',
                     :keywords => 'Locadora, Locações, Pendentes'

Caso você queira, pode ainda usar opções extras para personalizar seus títulos:

:prefix – Para não mostrar o nome do site antes por exemplo, ou mostrar outro conteúdo

Ex.: <%= title ‘Locações pendentes’, :prefix => false %> #–> <title>Locações pendentes</title>

:separator – Texto usado para separar o nome do site do nome da página.

Ex.: <%= title ‘Locações pendentes’, :separator => “:” %> #–> <title>Locadora : Locações pendentes</title>

:reverse – Quando verdadeiro, inverte a posição no nome do site e o nome da página.

Ex.: <%= title ‘Locações pendentes’, :reverse => true %> #–> <title>Locações pendentes | Locadora</title>

Outras opções e formas de uso são melhor detalhadas no arquivo README.rdoc, que se encontra na pasta do plugin.

O plugin meta-tags facilita o gerenciamento do conteúdo de tags que são de suma importância para ter um website bem posicionado. Conteúdo esse que fica mais difícil de individualizar para cada view a medida que a aplicação cresce. Uma boa prática para o uso deste plugin é setar valores padrão das tags no controller da aplicação (application.rb) e depois customizar o conteúdo nas views.

Nos próximos posts desta série, teremos mais dicas de plugins para melhorar o SEO das suas aplicações Rails. Aguardem…

Leia mais sobre SEO:

Ruby Tips: Iterando em Arrays

Ruby sempre me atraiu pela facilidade com que posso usar as classes Array e Hash para manter estruturas de dados que em outras linguagens eu teria a necessidade de usar classes especiais, normalmente um classe para cada tipo de elemento, o que sempre deixava o código cheio de typecasts e muitos laços FOR ou WHILE para fazer iterações. Diferente de outras linguagens, em Ruby tudo é um objeto, inclusive um Array, que possui métodos que auxiliam na própria iteração com seus elementos. Todos esses métodos de iteração recebem um bloco de código que é executado para cada elemento do Array. Vou mostrar alguns exemplos de uso abaixo, então abra o IRB e vamos testar cada um deles:

numbers = [1, 2, 3, 4, 5]

Vou usar esse array como padrão para os exemplos.

Método Each

O método EACH recebe um bloco de código que será executado para cada elemento do Array. Cada elemento é passado para o bloco como parâmetro durante a iteração. Com isso podemos realizar operação com cada elemento, como por exemplo, imprimir uma frase com cada valor:

numbers.each do |number|
puts "Linha de numero #{number}"
end

Produzirá:
Linha de numero 1
Linha de numero 2
Linha de numero 3
Linha de numero 4
Linha de numero 5

Método Select

O método SELECT recebe um bloco de código que é executado para cada elemento. A diferença com o EACH é que enquanto este não retorna nenhum valor, o SELECT retorna um outro Array. Vamos comparar a utilização dos dois com um exemplo de seleção de números pares:

even = []
numbers.each do |number|
even < < number if number %2 == 0
end

Adicionamos ao Array even números com o resto da divisão por 2 igual a zero, obtendo [2,4]. Vejamos como o SELECT torna isso ainda mais fácil:

even = numbers.select do |number|
number % 2 ==0
end

Método Inject
O método INJECT também chama um bloco de código para cada iteração, mas com a diferença de passar 2 parâmetros a esse bloco. O primeiro deles é um acumulador e o segundo é o elemento. Vamos novamente comparar sua utilização com o EACH com um exemplo onde somamos todos os valores do Array numbers, primeiro usando o EACH e depois usando o INJECT:    

sum = 0
numbers.each do |number|
sum += number
end

sum = numbers.inject do |a, number|
a + number
end

O INJECT pode ainda receber um parâmetro, que é usado como valor inicial para o acumulador. Exemplo:

sum = numbers.inject(10) do |a, number|
a + number
end

Com o valor inicial sendo 10, sum passaria a ter o valor 25.

Método Map

O método MAP realiza a mesma iteração em um bloco de código como nos métodos anteriores, mas a resposta é um novo Array, com novos elementos baseado em operações aplicadas a cada elemento. Desta vez vamos comparar sua utilização com o EACH criando um Array com os valores de numbers multiplicados por 10. 

new_numbers = []
numbers.each do |number|
new_numbers < < number * 10
end

new_numbers = numbers.map do |number|
number * 10
end

Depois de qualquer uma das chamadas acima, new_numbers será [10,20,30,40,50]. Logicamente o uso do método MAP neste caso é mais limpo e elegante.

Espero que tenha esclarecido a diferença de uso dos iteradores de Array existentes em Ruby. Lembrando que esses mesmos métodos também existem em classes Hash. Tecnicamente a única diferença entre Arrays e Hashs é que na primeira classe os índices dos elementos são números inteiros, enquanto que um Hash por ter qualquer tipo de objeto como índice.

Fonte: RailsSpikes

Aplicações brasileiras em Rails e conferência Rails em outubro

Todo mundo que já pesquisou um pouco sobre Ruby ou Rails passou a conhecer Fábio Akita. Ele tem trabalhado bastante para tornar o desenvolvimento em Ruby On Rails cada vez mais popular aqui no Brasil. Para quem ainda não conhece (paraquedista com certeza =D), ele é um dos pioneiros a utilizar a tecnologia, escreveu o primeiro livro em português sobre o assunto e agora está à frente da equipe Rails da Locaweb, para oferecer uma hospedagem de qualidade seguindo o padrão dos hostings internacionais.

A fim de divulgar projetos de brasileiros feitos com Rails, ele publicou em seu blog uma lista de aplicativos que usam o framework e foram criados por brasileiros. Fico muito agradecido por ter um projeto citado entre outros tão importantes e que me serviram como inspiração. O Sismiko apareceu entre nomes como BlogBlogs, TreinaTom, Pagestacker, Mapia, Investidor Virtual e Ikwa, só para citar alguns.

Espero que o Sismiko também inspire desenvolvedores recém chegados ao Rails à transformar suas idéias em realidade. Não deixe de conferir a lista completa de aplicativos e até sugerir algum que você conheça mas tenha ficado de fora.

Se meus planos se confirmarem, poderei encontrar os desenvolvedores desses aplicativos na Rails Summit Latin América que acontece em Outubro, no Anhembi em São Paulo. Se você estava dando uma voltinha por Marte nos últimos dias =D, não deve saber que esta será, com certeza, a maior conferência sobre Rails realizada abaixo da linha do Equador. Nas palavras do próprio Akita:

Teremos alguns dos maiores Railers da comunidade internacional como David Hansson, Charles Nutter, Chad Fowler, Dr. Nic, Chris Wanstrath, David Chelinsky e muito mais, em dois dias inteiros, com duas sessões paralelas, incluindo almoço, coffee break por R$ 300 (cerca de USD 190).

Além dessas atrações internacionais, teremos palestras de brasileiros empreendedores Rails: Manoel Lemos do Brasigo e BlogBlogs, Carlos Eduardo da e-Genial e Treina Tom, Fabio Kung da Caelum, Vinicius Teles da Improve it (nosso famoso evangelista de XP) e George Guimarães do Pagestacker.

O site oficial do evento será lançado em breve, com venda de ingressos e dicas de transporte e hospedagem.

BDD com Shoulda: Menos código, testes mais legíveis

Para quem ainda não conhece, BDD (Behavior Driven Development) é uma prática de processos ágeis que vem mudando a maneira como os desenvolvedores escrevem testes automatizados para seus sistemas.  Testes escritos sobre este conceito são mais fáceis de entender e podem ser utilizados como ferramenta de modelagem de um sistema, já que eles ajudam pessoas com pouco conhecimento técnico à entender funcionamento do software. Além disso, testes simples de entender também são simples de manter.

Essas vantagens me fizeram pensar na idéia de migrar os testes do meu projeto Rails, que tinha seus testes unitários escritos sobre o framework Test/Unit, o padrão utilizados pelo Rails para TDD (Test Driven Development). Para realizar a mudança era necessário aprender a utilizar outro framework, no caso o RSpec.

Foi então que, acompanhando a blogosfera de Railers, através de um post do Carlos Brando, conheci o Shoulda. O Shoulda é um framework recente e que eu considero como um passo intermediário entre o Test/Unit e o RSpec. Ele traz um conjunto de classes e métodos que melhoram o Test/Unit padrão, permitindo o uso de uma sintaxe parecida com a do RSpec. Assim é possível se aproximar de BDD sem ter muito impacto na forma de programar os testes.

Vou exemplificar aqui o migração dos testes de um model simples do Sismiko, a classe City que possui apenas os atributos “name” e “state_id”, representando o nome da cidade e o id do estado, respectivamente.

Observe o código utilizando o modo padrão:

class CityTest < Test::Unit::TestCase

fixtures :cities

  def test_name_required #testa se o nome da cidade é um campo requerido

    check_required(:name)

end

def test_state_required #testa se o campo state_id da cidade é um campo requerido

check_required(:state_id)

end

def test_max_name #testa se o tamanho máximo do campo nome é de 100 caracteres

city = create(:name => "a" * 101)

assert city.errors.invalid?(:name),"name must have a maximum of 100 chars"

assert_not_nil city.errors.on(:name)

assert !city.valid?, "city shouldn't be created"

end

private

def create(options={}) #cria uma cidade padrão

City.create({

:name => "Maringá",

:state_id => 1

}.merge(options))

end

def check_required(att) #verifica se o campo passado em att é requerido pelo objeto

city = create(att => nil)

assert city.errors.invalid?(att)

assert_not_nil city.errors.on(att)

assert !city.valid?, "city shouldn't be created"

end

end

No código acima vemos três testes sendo feitos e mais dois métodos auxiliares, para criar um objeto com valores padrão em seus atributos e outro para verificar se um atributo é requerido. Quanto as testes, o primeiro e o segundo testes verificam se os campos “name” e “state_id” são obrigatórios ao criar um objeto de cidade. O terceiro verifica se o campo “name” aceita no máximo 100 caracteres.

Vejamos agora o código necessário para fazer os mesmo testes, usando a declaração de contextos pregada pelo BDD para deixar os testes mais legíveis, já utilizando o Shoulda:

class CityTest < Test::Unit::TestCase

fixtures :cities

context "A City instance" do

setup do

@city = create

end

should "have a required name" do

check_required(:name)

end

should "have a required state" do

check_required(:state_id)

end

context "with a large name" do #uso de contexto aninhado

setup do

@city.name = "a" * 101

@city.save

end

should "validate max size of name" do

assert city.errors.invalid?(:name)

end

end

end

private

def create(options={}) #cria uma cidade padrão

City.create({

:name => "Maringá",

:state_id => 1

}.merge(options))

end

def check_required(att) #verifica se o campo passado em att é requerido pelo objeto

city = create(att => nil)

assert city.errors.invalid?(att)

assert_not_nil city.errors.on(att)

assert !city.valid?, "city shouldn't be created"

end

end

Com certeza ficou mais fácil de entender e também de localizar o erro. Por exemplo, caso o teste de atributo “name” requerido falhe, recebemos a seguinte mensagem:

test: A City instance should have a required name

O uso do novo framework melhorou a legibilidade dos testes, mas podemos melhorar ainda mais. Fazendo uso de helpers acrescentados pelo Shoulda, é possível reduzir o código para algo assim:

 
CityTest < Test::Unit::TestCase

  fixtures :cities

  should_require_attributes :name, :state_id #1

  should_ensure_length_in_range :name, (0...100) #2

end

Sem dúvida, muito mais simples. A linha comentada com #1 substitui dois testes escritos anteriormente, validando os campos “name” e “state_id” como requeridos. Em #2 verifica-se se o atributo “name” aceita valores com tamanho entre 0 e 100, rejeitando valores maiores.

Ficou impressionado? Instale o Shoulda e faça suas experiências, o projeto está no github:

script/plugin install git://github.com/thoughtbot/shoulda.git

Veja também:

O Lucas Hungaro fez um screencast muito bacana com uma introdução ao Shoulda.

Existem vários outros helpers além dos apresentados aqui. A documentação de todos eles pode ser encontrada na documentação do projeto.