Utilizando o named_scope no ActiveRecord do Ruby on Rails 2.1
Leia em 1 minuto
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!