Search code examples
rubymetaprogrammingaliasattr-accessor

Assignment methods are not aliased properly


Consider the following code:

class Cattr
  attr_accessor :attr
  alias_method :a_attr, :attr
  alias_method :a_attr=, :attr=
  def attr ; a_attr ; end
  def attr= value ; a_attr= value ; end
end
ca = Cattr.new
#⇒ #<Cattr:0x000000018974b0>
ca.attr
#⇒ nil
ca.attr = 42
#⇒ 42
ca.attr
#⇒ nil

What? The problem is not with aliasing method, defined by attr_accessor, aliasing getter works pretty fine:

class Cattr
  attr_accessor :attr
  # alias_method :a_attr=, :attr=
  alias_method :a_attr, :attr # still aliased
  # def attr= value ; a_attr= value ; end
  def attr ; a_attr ; end     # still aliased
end

ca = Cattr.new
#⇒ #<Cattr:0x000000018974b0>
ca.attr
#⇒ nil
ca.attr = 42
#⇒ 42
ca.attr
#⇒ 42   # sic!

Sidenote: aliasing attr? method works pretty fine too.

My question would be: is it a known ruby behaviour (aliasing setters is prohibited,) or I am missing something obvious?


Solution

  • Setter methods need explicit receivers. Your code:

    def attr= value ; a_attr= value ; end
    

    is not calling the setter a_attr=; it is assigning a value to a local variable a_attr.

    To do what you want, you need to do:

    def attr= value; self.a_attr= value; end