10

send can be used to call public as well as private methods.

Example:

class Demo
  def public_method
    p "public_method" 
  end

  private

  def private_method
    p "private_method" 
  end
end

Demo.new.send(:private_method)
Demo.new.send(:public_method)

Then where and why to use public_send?

Tamer Shlash
  • 9,314
  • 5
  • 44
  • 82
Kalyani Kirad
  • 309
  • 3
  • 12
  • My question is if send can call public as well as private method then when and why to use public_send? – Kalyani Kirad Mar 22 '16 at 11:09
  • AFAIK `send` exists since the first version of ruby, but `public_send` is introduced quite late in order to meet the taste of those who prefer strict encapsulation. – Aetherus Mar 22 '16 at 11:10
  • Use `public_send` when you intend to call public methods and are not trying to mess with internals. This way you communicate your intent to future readers of your code. – Sergio Tulentsev Mar 22 '16 at 11:12
  • Does this answer your question? [What is the difference between Ruby's send and public\_send methods?](https://stackoverflow.com/questions/30401970/what-is-the-difference-between-rubys-send-and-public-send-methods) – BinaryButterfly Jul 02 '22 at 19:49

1 Answers1

18

Use public_send when you want to dynamically infer a method name and call it, yet still don't want to have encapsulation issues.

In other words, public_send will only simulate the call of the method directly, no work arounds. It's good for mixing encapsulation and meta programming.

Example:

class MagicBox
  def say_hi
    puts "Hi"
  end

  def say_bye
    puts "Bye"
  end

  private

  def say_secret
    puts "Secret leaked, OMG!!!"
  end

  protected

  def method_missing(method_name)
    puts "I didn't learn that word yet :\\"
  end
end

print "What do you want met to say? "
word = gets.strip

box = MagicBox.new
box.send("say_#{word}")        # => says the secret if word=secret
box.public_send("say_#{word}") # => does not say the secret, just pretends that it does not know about it and calls method_missing.

When the input is hi and secret this is the output:

What do you want met to say? hi
=> Hi
=> Hi

What do you want met to say? secret
=> Secret leaked, OMG!!!
=> I didn't learn that word yet :\\

As you can see, send will call the private method and hence a security/encapsulation issue occurs. Whereas public_send will only call the method if it is public, otherwise the normal behaviour occurs (calling method_missing if overridden, or raising a NoMethodError).

Tamer Shlash
  • 9,314
  • 5
  • 44
  • 82