0

I can't understand this behavior. Please point me to a detailed answer. I created an object of class Parent:

class Parent
  private
  def name
    'Mommy'
  end
end
p = Parent.new

This raises an error:

p.name
# => NoMethodError: private method `name' called for #<Parent:0x0000000182a360>

but, the following gives the value.

p.send(:name)
# => "Mommy" 
sawa
  • 165,429
  • 45
  • 277
  • 381
  • Thanks everyone for the wonderful insights. Can anyone share a link with detailed info. – user3493806 Apr 04 '14 at 04:41
  • While digging deeper, i found that setter method can be called with explicit receiver for private methods. Please check this link for the example. https://www.ruby-forum.com/topic/157911 – user3493806 Apr 04 '14 at 09:11

3 Answers3

2

That is the whole point of private methods. In the first form, you have an explicit receiver. In the second form, you don't.

sawa
  • 165,429
  • 45
  • 277
  • 381
1

In Ruby, private methods can't be invoked with an explicit receiver. -- This is a rule hard-coded. If you try, MRI will object/complain as what you got.

But using #send, you are not breaking the rule, thus no objections.

p.send(:name), you are calling method #send on p, and at the same time passing the method name(:name) as a symbol, to call the method. This is indeed a indirect approach. But in p.name, it is a direct method call of the method #name on p. That's all the differences about the 2 approaches.

No where it is written, you can't call private methods, but it is written, not with explicit receiver, you can call it.

Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
0

The send method can access any method, whether it's public, private, or protected. If you want a method that respects methods' privacy, try public_send.

Wally Altman
  • 3,535
  • 3
  • 25
  • 33