Can you call private methods with explicit receivers?

My understanding is the answer is no, you can’t call private methods
with explicit receivers, even self. See
http://www.skorks.com/2010/04/ruby-access-control-are-private-and-protected-methods-only-a-guideline/

However, the following example seems to counter that.

class A
def m2
self.m1 = “hello”
self.m3
end

private

def m1=(value)
@m1 = value
puts “assigning #{value} to @m1
end

def m3
puts “inside m3”
end
end

A.new.m2

The output is:
assigning hello to @m1
/tmp/t.rb:4:in m2': private methodm3’ called for #<A:0x007fc4b404e568
@m1=“hehe”> (NoMethodError)
from /tmp/t.rb:19:in `’

Why can m2 call self.m1= which is a private method?

$ ruby –v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.3.0]

Best,
Jingjing

2012/7/5 Jingjing D. [email protected]:

Why can m2 call self.m1= which is a private method?

Probably because it would be otherwise impossible (except for using
#send), as m1 = "hello" would have been local variable assignment
and not method call.

– Matma R.

Thanks Bartosz. That makes sense. I guess due to Ruby’s rich syntax it
has to make some exceptions like this one under certain circumstances.

BTW, I found the blog post below which talks about this exact problem.

http://pivotallabs.com/users/pjaros/blog/articles/1968-private-setters-in-ruby-what-to-do-

Bartosz Dziewoński wrote in post #1067565:

2012/7/5 Jingjing D. [email protected]:

Why can m2 call self.m1= which is a private method?

Probably because it would be otherwise impossible (except for using
#send), as m1 = "hello" would have been local variable assignment
and not method call.

– Matma R.

On Thu, Jul 5, 2012 at 6:16 PM, Jingjing D. [email protected]
wrote:

end
end
Picking up Bartosz Dziewoński’s reference to #send, also note this:

A.new.m2 rescue puts $!.inspect
A.new.m3 rescue puts $!.inspect
A.new.send(:m3) rescue puts $!.inspect

produces:

assigning hello to @m1
#<NoMethodError: private method m3' called for #<A:0x9ba3a0 @m1="hello">> #<NoMethodError: private methodm3’ called for #<A:0x9b9ac0>>
inside m3