On Thu, Jun 26, 2014 at 1:02 PM, Steve Tooke <steve.tooke / gmail.com> wrote:
> On Thu, Jun 26, 2014 at 10:58 AM, Robert Klemme
> <shortcutter / googlemail.com> wrote:
>>
>> Why would you?  bar= _is_ defined.
>
> That's how ruby responds when you try to call a private method using
> the explicit self receiver:

Oh right.  I thought it was another error.  I just looked at the
message. I'm sorry.

> But the same rules don't seem to follow when using the `=` operator

Right.  Apparently that is handled specially.  That makes sense if you
consider that there is no other way to invoke assignment methods other
than prefixing with "self.".

> I'm guessing that the `=` operator essentially results in doing a send
> to `"#{method_name}=` and therefore is bypassing ruby's usual method
> visibility rules.

I don't think it necessarily needs to go through #send to allow this
to happen.  There just needs to be a different call chain for things
like "self.{identifier}={expression}".  But we can test:

$ ruby xx.rb
42
SEND
43
$ cat xx.rb
class Foo
  def send(*x) puts "SEND"; super end

  private
  attr_accessor :bar

  public
  def set_bar(b)
    self.bar = b
  end

  def set_bar_2(b)
    send("bar=", b)
  end

  def get_bar
    bar
  end
end

f = Foo.new
f.set_bar(42) # no warning except under -w
puts f.get_bar # outputs 42
f.set_bar_2(43)
puts f.get_bar # outputs 43


Voil!


>> Btw. 1.9.3 also did not choke with this.
>
> Yep - also 1.8.7 and rubinius 2.2.2 - so I guess this is expected
> behaviour. It just surprised _me_ :)

I also was not aware. Learn something new every day. :-)

Kind regards

robert

-- 
[guy, jim].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/