Ruby: un simpatico problema con attr_accessor

Implementando la solita libreria di import-export, ho incontrato un curioso problema con attr_accessor

avendo dichiarato i metodi di set e get per una variabile di istanza da usare come contatore degli errori con il solito attr_accessor( :n_err), al momento di incrementare il numero di errori rilevati si scatena un orribile :

 get NoMethodError: undefined method '+' for nil:NilClass

Questo è il codice minimo che potete usare per replicare l’errore:

class Foo
  attr_accessor :x

  def initialize
    @x = 0
  end

  def bar
    x += 1
  end
end

Evidentemente Ruby nel trasformare x += 1 in x = x + 1 rileva l’inesistenza di x e crea una variabile locale assegnandole il valore nil,  da cui l’errore.

Il punto è che mi aspettavo, avendo dichiarato i metodi di get e set, che accedesse ad x utilizzando appunto il metodo getter generato automaticamente da attr_accessor 😡

def x
   @x
end

ma evidentemente non è cosi!

Se modifico il metodo bar facendo un riferimento esplicito all’istanza il problema non si verifica:

def bar
   self.x += 1
end

in questo articolo sul sito MetaRuby è contenuta una interessante trattazione del problema.