Formatando datas no Ruby on Rails

31/08/07

Imagine que você tenha um campo datetime e que você queira exibir logo abaixo de um post de blog. Você poderia criar um helper para fazer isso:

class PostsHelper
  def post_date(date)
    # formatting date: Aug, 31 2007 - 9:55PM
    date.strftime("posted on %b, %m %Y - %H:%M")
  end
end

E em seu template poderia chamar algo como:

<%= post_date @post.created_at %>

Você também poderia fazer esta formatação no modelo, utilizando o método after_find:

class Post < ActiveRecord::Base
  private
    def after_find
      self.created_at = created_at.strftime("posted on %b, %m %Y - %H:%M")
    end
end

Porém, a maneira mais interessante de se formatar datas no Rails, é utilizando o método to_s; tudo o que você precisa fazer é definir um novo formato. Para fazer isso, adicione a seguinte linha ao seu arquivo "environment.rb":

Time::DATE_FORMATS[:post] = "posted on %b, %m %Y - %I:%M%p"

Para exibir a data devidamente formatada, basta chamar o método to_s passando o formato que você quer utilizar.

<%= @post.created_at.to_s(:post) %>

Lembre-se que você pode definir quantos formatos quiser:

Time::DATE_FORMATS[:archive] = "%B/%Y"
Time::DATE_FORMATS[:updated] = "updated on %b, %m %Y - %I:%M%p"

Executando SQL no Rails

23/08/07

Às vezes precisamos realizar consultas que não pertencem a nenhum modelo no Rails. Uma maneira de fazer isso é utilizando o método execute. Veja um exemplo:

# setting a variable
# with the current connection
conn = ActiveRecord::Base.connection

result = conn.execute "SELECT id, email FROM users LIMIT 3"
# => #<Mysql::Result>

Como resultado, você recebe um objeto Mysql::Result, que pode ser iterado da seguinte maneira:

result = conn.execute "SELECT id, email FROM users LIMIT 2"
result.each do |user|
  puts "id: %s" % user[0]
  puts "email: %s" % user[1]
  puts
end

Normalmente, precisamos fazer consultas baseadas em valores passados pelo usuário. É extremamente importante que você tome os cuidados necessários para não sofrer um ataque através de SQL Injection. Para que isto não aconteça, você deve utilizar o método quote:

query = "SELECT id, email FROM users WHERE email = %s" % conn.quote("' OR 1=1 #")
puts query
# => SELECT id, email FROM users WHERE email = '\' OR 1=1 #'

Além do método execute, você pode utilizar outros mais específicos como é o caso do método select_all. Este método retorna um array de hashes, com o nome das colunas como índice, tornando mais simples a iteração.

result = conn.select_all "SELECT id, email FROM users LIMIT 2"
result.each do |user|
  puts "id: %s" % user['id']
  puts "email: %s" % user['email']
  puts
end

Para os casos em que tudo o que você precisa é de apenas uma linha como resultado, você pode utilizar o método select_one:

result = conn.select_one("SELECT COUNT(*) AS total FROM users")
puts result['total']

No Rails, todos os modelos estendem a classe ActiveRecord::Base. Por isso, os métodos acima também estão disponíveis no modelo.

class User < ActiveRecord::Base
  def self.all
    connection.select_all "SELECT id, email FROM users"
  end
end
 
puts User.all
# => [{"id"=>"1", "email"=>"user@example.com"}, {"id"=>"2", "email"=>"another@example.com"}]

Lembre-se que não é nenhuma vergonha utilizar SQL diretamente no Rails. O que o ActiveRecord faz é nos poupar das tarefas rotineiras. Já para as mais complexas, você provavelmente vai precisar de uma das soluções acima. Para mais informações, acesse a documentação do ActiveRecord.

Rails Rumble

17/08/07

Logo do RailsRumble Se você tem uma idéia bacana e acha consegue finalizá-la em 48h, prepare-se: Rails Rumble é o incentivo que você precisava! O concurso acontecerá nos dias 8 e 9 de setembro e oferecerá toda a estrutura necessária para fazer o deployment de sua aplicação.

A lista de prêmios não saiu ainda, mas provavelmente terá coisas bastante interessantes, por conta do patrocinadores do concurso: O'Reilly, Apress e Pragmatic Bookshelf, dentre outros.

Se você quer participar, não deixe de ler o regulamento do concurso. Eu já fiz minha inscrição, pois tenho algo em mente. Vamos ver!

Update: Inscrições abertas! Vai lá e cadastra seu projeto, pois apenas 150 vagas foram disponibilizadas. Quando me inscrevi estava no #67.

Update 2: Meu app já tem um nome: waavo. De onde saiu? Pergunta para ele!