Fuentes Vinícius Baggio - Ruby on Rails: coloque sua aplicação web nos trilhos стр 12.

Шрифт
Фон

3.days.from_now). Fica bem difícil lembrar o que cada parâmetro significa e pior,

qual é a ordem desses parâmetros. Ou mais além, no Rails, por exemplo, é possível

passar algumas opções para mudar algum comportamento do método. Este tipo de

problema é o chamado acoplamento por posição, ou seja, o código torna-se com-

plicado devido à grande dependência da posição dos parâmetros.

Por isso, é bem comum usar hashes como parâmetros para tornar a chamada de

método mais legível e evitar que o programador fique consultando manuais a todo

momento:

search_flights(:from => 'SAO', :to => 'NYC')

search_flights(:from

=> 'SAO',

:to

=> 'NYC',

:max_stops => 3,

:class

=> :first)

Resumindo, os principais usos para hashes como parâmetros são:

Independência de ordem de parâmetros, reduzindo acoplamento por posição;

Quando há muitos parâmetros;

Quando há parâmetros opcionais;

Quando é possível alterar o comportamento através de opções.

43

2.5. Funções, blocos, lambdas e closure

Casa do Código

Saiba mais: acoplamento por posição

Para entender melhor sobre este tipo de dependência e acoplamento, re-

comendo a leitura do artigo Connascence as a Software

Design Metric

[4] do Gregory Brown e também ver a palestra Building Blocks of Mo-

dularity [10], do Jim Weirich.

Nesses casos, é bastante comum métodos serem construídos da seguinte ma-

neira:

# Se nada for passado, todos os parâmetros serão os default

def search_flights(options={})

from

= options.fetch(:from, 'SAO')

to

= options.fetch(:to, '')

max_stops

= options.fetch(:max_stops, 9999)

flight_class = options.fetch(:class, :any)

# ...

end

Blocos associados a métodos

Vimos no final da seção 2.4 o funcionamento de blocos. Agora veremos como

construir funções que possuem comportamento semelhante. O procedimento é bas-

tante simples, basta usarmos duas expressões: yield e block_given?.

O yield passa o fluxo de execução do programa para o bloco associado ao mé-

todo ou função. Usamos o block_given? para verificar se algum bloco foi passado

de fato ao método. Observe os exemplos a seguir:

def announce_it

puts "Legen..."

yield

puts "Dary!"

end

announce_it { puts "Wait for it!" }

# Legen...

# Wait for it!

# Dary!

44

Casa do Código

Capítulo 2. Conhecendo Ruby

announce_it

# Legen...

# LocalJumpError: no block given (yield)

Agora, usando o block_given?:

def announce_it

puts "Legen..."

# yield não executado caso não haja um bloco!

yield if block_given?

puts "Dary!"

end

announce_it { puts "Wait for it!" }

# Legen...

# Wait for it!

# Dary!

announce_it

# Legen...

# Dary!

Sintaxe alternativa para blocos

Existe uma forma de se usar blocos que não usa o par yield/block_given?. Essa

forma é explicitar o bloco com um parâmetro da função através do operador &, que

sempre deverá vir por último na lista de parâmetros:

def announce_it(name, &block)

puts "Hey #{name}, it's gonna be... "

puts "Legen..."

# Se o bloco não for passado, block será nil

block.call if block

puts "Dary!"

end

announce_it("Ted")

announce_it("Ted") { puts "Wait for it..." }

45

2.5. Funções, blocos, lambdas e closure

Casa do Código

Apesar de não recomendado, mesmo usando esta forma é possível usar yield e

block_given?. A grande vantagem de usar esta forma é para repassar o bloco para

outros métodos, sendo impossível com o yield:

def header(&block)

puts "Começa..."

# Precisamos transformar a variável

# em bloco novamente, por isso colocamos o &

[1,2,3].each(&block)

puts "Termina!"

end

header { |num| puts num }

# Começa...

# 1

# 2

# 3

# Termina!

# => nil

Sintaxe de blocos

A sintaxe de blocos mais usada por desenvolvedores que trabalham com

Rails é a mesma dos desenvolvedores do próprio Rails: explicitar os blo-

cos no parâmetro com &. O motivo é simples: documentação, ou seja,

fica claro para o leitor do código que aquele método pode receber um

bloco.

procs

Uma coisa interessante na sintaxe usando o operador & (apelidado também de

operador pretzel) é que o bloco é transformado em um objeto da classe Proc, que

responde ao método #call:

def block_it(&block)

puts block.class

end

46

Casa do Código

Capítulo 2. Conhecendo Ruby

block_it {} # Proc

Procs são estruturas amplamente utilizadas em projetos Ruby por diversas ra-

zões, sendo a possibilidade de transformá-las em blocos é apenas uma delas. É im-

portante ressaltar esse fato: blocos não são procs e vice-versa, mas são facilmente

transformados um no outro usando o &. Vejamos alguns exemplos:

logger = proc { |x| puts "#{Time.now} -- #{x}" }

logger.call("Teste!") # 2012-05-08 15:52:58 -0300 -- Teste!

[1,2,3].each(&logger) # O proc vira bloco para o each com o &

# 2012-05-08 15:53:46 -0300 -- 1

# 2012-05-08 15:53:46 -0300 -- 2

# 2012-05-08 15:53:46 -0300 -- 3

Um uso extremamente útil desses conceitos é que símbolos implementam o mé-

todo #to_proc, que é chamado pelo operador

&. Este proc resultante chama o mé-

todo do argumento cujo nome é o símbolo. Para ficar mais claro, vejamos os exem-

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке