Dev (Back & Front)ARTIGO

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 RubyRuby3 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.

é desenvolvedor Java, PHP e Ruby, que é seu principal foco desde 2004 e que lhe rendeu um livro.

Ver perfil