O que é “tentar”?
Você já acabou com esse código?
@person && @person.name
Estamos fazendo isso porque não sabemos aqui se @person
é nil
valor. No entanto, podemos refatorar essa linha com try
:
@person.try(:name)
Que é equivalente a
@person.nil? ? nil : @person.name
Portanto, nenhuma exceção é levantada e o name
método é chamado se @person
for nil
. Nós estamos felizes:)
Argumentos
O primeiro argumento é o nome do método e outros argumentos são passados como argumentos para o método chamado.
@people.take(5)
pode ser escrito como:
@people.try(:take, 5)
Encadeamento de Método
try
o método retorna sempre nil
se chamado no nil
objeto:
nil.try(:foo) # => nil
Graças a isso, podemos refatorar isso:
@person && @person.name && @person.name.downcase == "Kavinsky"
para isso:
@person.try(:name).try(:downcase) == "Kavinsky"
Você pode ir ainda mais longe para evitar a repetiçãotry
:
"Don'tRepeatYourselfs ".try_chain(:underscore, :capitalize, :chop!, :chop!)
De onde vem a tentativa ?
try
método é definido em Object
classe e NilClass
classe em Rails e não faz parte do Ruby em si. No entanto, se você quiser usá-lo sem Rails, pode instalar activesupport
apenas o gem e chamar:
require 'active_support/core_ext/object/try'
Você realmente precisa tentar?
Estou me perguntando se você precisa usar o try . Tive um grande problema em encontrar um exemplo real, então peguei no código-fonte do Rails. Vamos dar uma olhada em alguns exemplos de outra postagem do blog que descreve como tentar evitartry
@manufacturer.products.first.try(:enough_in_stock?, 32) # => "Yes"
Por que diabos você faria essa consulta?
@manufacturer.products.try(:collect) { |p| p.name } # => ["3DS", "Wii"]
Aqui você pode usar since retornará um array que responde a (se você usar associação no modelo).@manufacturer.products.collect
products
collect
has_many
Que tal este? É try
realmente necessário aqui?
if current_user.try(:is_admin?)
Não temos que usar try
se representarmos um caso especial como outro objeto (como na seção 2.2 do livro Confident Ruby). O problema try
quer resolver é que nós não queremos para obter NoMethodError chamando no objeto. Portanto, o que podemos fazer é fazer o objeto responder ao método desejado , definindo o método. O método pode realmente retornar uma instância da seguinte classe se o usuário não estiver conectado:is_admin?
nil
is_admin?
current_user
class GuestUser
def is_admin?
false
end
end
Agora você pode usar:
if current_user.is_admin?
Conclusão
try
pode tornar seu código mais curto quando você está lidando com objetos nulos em potencial. No entanto, eu sempre pensaria no redesenho do código primeiro, antes de injetar try
em seu código.
Nota:
Apenas por uma questão de integridade, o método try aceita um bloco.
Mais sobre isso aqui http://api.rubyonrails.org/classes/Object.html#method-i-try
2.0.0p195, Rails 3.2