Ruby Conditional-Assignment and Private Methods

memoization, ruby

Solution

That looks like a bug.

UPDATE: The bug was fixed in trunk, and is slated for back porting to 2.1 and 2.0.

Note that the problem is more general than that, it is broken for all abbreviated assignments, not just conditional abbreviated assignments:

private def foo=(*) end
public  def foo; 0  end

self.foo =  42

self.foo += 42
# private method `foo=' called for main:Object (NoMethodError)

private :foo

self.foo += 42
# private method `foo' called for main:Object (NoMethodError)

Problem

From the code below, it appears the `||=` operator is being evaluated from outside of the class. ``` class Foo attr_reader :bar def baz self.bar ||= 'baz' end private attr_writer :bar end puts Foo.new.baz # => in `baz': private method `bar=' called for #<Foo:0x007fd9720829a8> (NoMethodError) ``` Quoting from the accepted answer on Official expansion of ||= conditional assignment operator: ``` In other words, the expansion c = c || 3 is (excluding bugs like in pre-1.9) correct. ``` Rewriting the `baz` method as `self.bar = self.bar || 'baz'` does not raise the error. I am looking for a definitive answer on how and why Ruby is behaving in this way, since it seems counter-intuitive. This behaviour is present on Ruby versions 1.9.3, 2.0.0 and 2.1.2, which leads me to believe this is not a bug.

Original source

Related problems