Utilizando o named_scope no ActiveRecord do Ruby on Rails 2.1

14 de Julho de 2008

O Ruby on Rails 2.1 trouxe uma série de novidades em quase todos os módulos do framework. Uma das novidades que mais gostei foi o named_scope, que permite criar buscas personalizadas, sem perder a elegância. Veja como usar todo o poder desta funcionalidade neste artigo.

Exemplos de uso

Imagine que você tenha dois modelos: Band e Genre.

class CreateBands < ActiveRecord::Migration
  def self.up
    create_table :bands do |t|
      t.string :name
      t.references :genre
 
      t.timestamps
    end
  end
 
  def self.down
    drop_table :bands
  end
end
 
class CreateGenres < ActiveRecord::Migration
  def self.up
    create_table :genres do |t|
      t.string :name
      t.timestamps
    end
  end
 
  def self.down
    drop_table :genres
  end
end
 

Antes do Ruby on Rails 2.1, se você quisesse criar consultas personalizadas poderia criar métodos ou estender as associações. Por exemplo, poderíamos implementar uma busca pelos artistas recentes ou de um gênero.

class Band < ActiveRecord::Base
  belongs_to :genre
 
  def self.recent
    all :order => "created_at desc"
  end
 
  def self.by_genre(genre)
    all :conditions => {:genre_id => genre}
  end
end

Mas como você faria se quisesse todos os artistas recentes de um gênero? E se você quisesse adicionar mais uma condição, como a primeira letra do nome do artista? É quando a coisa se complica! Se você usar o named_scope, pode escrever o exemplo anterior desta maneira:

class Band < ActiveRecord::Base
  belongs_to :genre
 
  named_scope :recent, :order => "created_at desc"
  named_scope :by_genre, lambda {|genre| {:conditions => ["genre_id = ?", genre] }}
end

Ambas abordagens funcionam da mesma maneira quando acessadas sozinhas, como Band.recent ou Band.by_genre(params[:genre_id]). A difença principal do named_scope é que você pode fazer chamadas encadeadas, propagando as opções de consulta. Note que não é preciso seguir nenhuma ordem específica nas chamadas.

Band.recent.by_genre(params[:genre_id])
Band.by_genre(params[:genre_id]).recent

Todas as buscas adicionadas pelo named_scope se comportam como objetos do ActiveRecord. Você pode executar contagens, fazer outras buscas ou agir ativamente nos resultados retornados.

Band.by_genre.first(:conditions => ["name = ?", params[:name]])
Band.recent.reload
Band.recent.count
Band.by_genre(params[:genre_id]).fans.average(:fans_count)

Se você ainda não usa o named_scope, comece a usá-la agora mesmo! Ele é, sem dúvida, uma das melhores funcionalidades do ActiveRecord. Não sei como pude viver sem isto até agora!

Posts relacionados
Como migrar suas Stored Procedures no ambiente de teste

Comentários #

#1 Um pouco mais sobre named_scopes : Learning on Rails disse:
30 Jul 08, 12:23AM

[...] artigo sobre isso? Bom, não o escrevi, mas vou partir do ponto em que parou o Nando Vieira em seu artigo sobre named_scopes. Logo, assumo que você já sabe o que é um named_scope e conhece algumas possibilidades, como [...]

Deixe um comentário




Este blog usa o Gravatar.


Não é aceito código HTML: adicione-o no pastie.org ou paste.milk-it.net e poste apenas o link.

Se este é seu primeiro comentário, ele terá que ser aprovado antes de ser exibido.