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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With