Carlos Brando

Nome do Jogo

Magica no Ruby com blocos e símbolos

392125498_7752990e1e.jpg

Sem dúvida nenhuma o Ruby tem algumas mágicas que impressionam. Imagine por exemplo que eu queira pegar um array de strings e converter todas as palavras para maiúsculo, eu poderia fazer assim:

>> meu_array = %w(ruby on rails)
=> ["ruby", "on", "rails"]

>> meu_array = meu_array.map {|name| name.upcase}
=> ["RUBY", "ON", "RAILS"]

Bem simples. Para cada item do array eu executo o método upcase e armazeno o resultado na variável meu_array. Mas eu também poderia fazer assim:

>> meu_array = %w(ruby on rails)
=> ["ruby", "on", "rails"]

>> meu_array = meu_array.map(&:upcase)
=> ["RUBY", "ON", "RAILS"]

Acho que ficou ainda mais bonito: aplique o método upcase para cada elemento de meu_array. O que acha?

Como isto funciona?

Quando usamos o operador & na frente do nome de uma variável estamos dizendo que esta variável é um bloco. Mas no nosso caso :upcase não é um bloco e sim um símbolo. Neste caso o Ruby tenta converter nosso símbolo em um bloco chamando o método to_proc da classe Symbol. Mas veja o código do método to_proc:

def to_proc
  Proc.new { |*args| args.shift.__send__(self, *args) }
end

Já entendeu? Este método transforma o símbolo :upcase em um bloco, fazendo com que o exemplo acima na verdade seja executado desta maneira:

>> meu_array = meu_array.map {|*args| args.shift.__send__(:upcase, *args)}
=> ["RUBY", "ON", "RAILS"]

Mágica? Você ainda não viu nada.

Agora imagine que eu tenha um classe User no Rails. Usando este recurso eu poderia fazer algo assim:

user = User.find(:all)

>> user.all?(&:valid?)
=> true

>> user.any?(&:valid?)
=> true

>> user.each(&:save!)

O Ruby tem as suas mágicas e o Rails sabe usa-las muito bem.

Comments