Rubismos – Configurações
Muitas Gems que usamos no dia a dia, utilizam o seguinte formato para realizar configurações:
MyLib.configure do |config| config.my_property = 25 end
Ou seja, estamos setando uma propriedade com o valor 25.
A Gem Capybara utiliza esta mesma abordagem. Veja abaixo:
Capybara.configure do |config| config.default_wait_time = 2 end
Vamos ver abaixo, como funciona esta implementação. Considere o seguinte código abaixo:
module MyLib class << self attr_accessor :my_property def configure yield self end end end MyLib.configure do |config| config.my_property = 2011 end puts MyLib.my_property
Basicamente estamos definindo um módulo chamado MyLib. Dentro dele, estamos definindo um accessor chamado my_property e também um método chamado configure.
Porém o accessor e o método, são definidos na singleton class do objeto MyLib.
Se você não entendeu muito bem esta questão de singleton classes, eu expliquei com mais detalhes no post “Ruby: relações e interações entre classes e objetos”.
A grande “sacada” está no método configure. Ele executa o método yield passando o self como parâmetro. Mas neste caso, quem será self? Self será o próprio módulo MyLib. Esta é a “chave” da questão.
É importante lembrar que o yield é o responsável por executar o bloco passado como parâmetro. E no exemplo acima, nosso bloco é:
do |config| config.my_property = 2011 end
Seguindo a ideia de como os blocos funcionam em Ruby, o módulo MyLib(que foi passado como self para o bloco) será mapeado para o config do bloco. Logo, quando fazemos config.my_property = 2011 de dentro do bloco, é como se estivéssemos fazendo MyLib.my_property = 2011.
Isso só foi possível pelo fato de termos definido um accessor para a nossa propriedade.
Uma outra abordagem que poderíamos utilizar para deixar a configuração um pouco mais modular seria com o seguinte código abaixo:
class Configuration attr_accessor :my_property def initialize @my_property = 'default value' end end module MyLib class << self attr_accessor :configuration end def self.configure self.configuration ||= Configuration.new yield(configuration) end end MyLib.configure do |config| config.my_property = "new value" end puts MyLib.configuration.my_property
Basicamente estamos armazenando um objeto de configuração dentro do nosso módulo.
6 Comentários »
Feed RSS dos comentários deste post URL de TrackBack

Boa!
Comentário por Lucas Catón — 13 de abril de 2011 @ 2:39
Acho muito verboso, prefiro o jeito Inploy
:
propriedade1 = valor
propriedade2 = valor
…
Comentário por Diego Carrion — 13 de abril de 2011 @ 2:58
Cara, muito legal o conteúdo. Gostei do exemplo quando tu passa uma instancia da classe Configuration pro bloco.
De fato, é uma prática muito comum em projetos populares.
Comentário por Matias Leidemer — 13 de abril de 2011 @ 16:49
Ótimo post!! Isso deixa seu código mais legível e organizado. Nunca tinha parado pra fazer algo desse tipo, vai ser muito útil pra mim. Obrigado!
Comentário por Mário Ramos — 13 de abril de 2011 @ 17:02
Carrion Marketeiro rs!! =)
Realmente, usar chave valor fica mais clean.
Acho que a maioria do pessoal que usa esta abordagem que eu citei acima, não gosta muito usar “eval” para setar “coisas”
Já via muita gente que ao criar DLS em Ruby por exemplo, evita ao máximo usar instance_eval nos blocos.
Comentário por Rinaldi Fonseca — 13 de abril de 2011 @ 17:34
Muito bom o post, agnt ve isso todo dia em projetos(rubistas), e nem se liga na metaprogramação que tem nisso. Congrats ;P
Comentário por Adimir Colen — 14 de abril de 2011 @ 6:47