Utilizando o padrão Singleton no Ruby
23/07/08
Singleton é um design pattern usado para restringir a instanciação de objetos, fornecendo um ponto global de acesso a uma única instância de uma classe.
No Ruby, você pode utilizar este padrão da maneira mais simples possível. Basta carregar a biblioteca Singleton.
require "singleton"
class Database
include Singleton
def connect
@connection = Adapter.connect
end
end
Ao adicionar o módulo Singleton, você torna o método new privado.
Se você tentar instanciar esta classe, verá um erro como este:
NoMethodError: private method `new' called for Test:Class
from (irb):3
from :0
Para ter acesso à instância da classe Test, você deve utilizar o método instance.
Database.instance.connect
Muito elegante, assim como quase tudo no Ruby!
- Permalink
- Trackback
- Comentários (1)
- Ao som de: Wonkavision – Rejection Junkie
Utilizando o named_scope no ActiveRecord do Ruby on Rails 2.1
14/07/08
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!
- Permalink
- Trackback
- Comentários (0)
- Ao som de: Kay Hanley – Mean Streak
Executando métodos sem se preocupar com exceções no Ruby
14/07/08
Cansado de ter que verificar se um objeto existe antes de chamar algum método ou acessar um atributo?
if @object && @object.some && @object.some.fancy && @object.some.fancy.call
# do something
else
puts "meh. i don't like this syntax!"
end
Concordo que isto não é muito comum, mas você já deve ter feito algo como isto:
if @object && @object.respond_to?(:some_method) && @object.some_method
# do something
end
Evite este tipo de aborrecimento trazido por estas verificações, adicionando um método como este:
def try(&block)
raise 'No block given' unless block_given?
yield rescue nil
end
if try { @objet.some.fancy.call }
# do something
else
puts 'hey! this call returned nil, false or threw an exception'
end
Muito mais com a cara de Ruby, não acha?
- Permalink
- Trackback
- Comentários (4)
- Ao som de: Kay Hanley – Mean Streak
