Referências circulares no Ruby 2.2.x
Rodando um projeto nessa versão, me lembrei de um detalhe importante, já consertado em gems mais novas, mas que vale a pena alertar.
Eu estava para escrever esse artigo faz algum tempo, desde que saiu a versão 2.2.0 da linguagem Ruby↳Ruby3 conteúdosComo migrei meus testes automatizados de Java para Ruby… Será que fiz bem?Dev (Back & Front) · jun 2019Refatoração em RubyDev (Back & Front) · mai 20197 exemplos de linguagens de programação server-sideGestão Dev & TI · jun 2024Ver tudo em Dev (Back & Front) →, mas nunca dava tempo… Até que, rodando um projeto nessa versão, me lembrei de um detalhe importante, já consertado em gems mais novas, mas que vale a pena alertar.
Vamos considerar o seguinte código:
class FooBar
def foo
"I'm in foo!"
end
def bar(foo = foo)
puts foo
end
end
foobar = FooBar.new
foobar.bar
foobar.bar("Not using foo!")
Podemos ver que temos dois métodos ali: foo, que retorna uma String, e bar, que utiliza um argumento com valor default, que no caso de não ter sido enviado, vai utilizar o retorno de foo. Rodando o código em uma versão menor que 2.2.x, é exibido o seguinte resultado:
<code>$ ruby circular.rb I'm in foo! Not using foo! </code>
Mas, rodando a partir da versão 2.2.0, temos o seguinte resultado:
<code>$ ruby circular.rb circular.rb:6: warning: circular argument reference - foo Not using foo! </code>
O que ocorre é que, a partir da versão 2.2.0, o argumento foo (à esquerda) está procurando uma variável foo (à direita), e como ela não existe e seria ali uma referência para a própria variável que está sendo criada na assinatura do método (daí a referência circular), é atribuído o valor de nil e disparado um warning.
Para utilizar o comportamento anterior nas versões a partir de 2.2.x, temos que fazer uma referência explícita ao método foo na linha 6, da seguinte maneira:
<code> def bar(foo = foo()) </code>
Algumas gems do Rails, dependendo da versão, estavam com esse tipo de problema (como por exemplo, o ActiveSupport), mas aparentemente em versões atuais, já foi resolvido. Na hora que forem rodar seus projetos com versões novas do Ruby a partir das 2.2.x, fiquem espertos com isso.





