Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use send and public_send methods in ruby?

Tags:

ruby

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?

like image 841
Kalyani Kirad Avatar asked Mar 22 '16 11:03

Kalyani Kirad


People also ask

How do you use the send method in Ruby?

Ruby Language Metaprogramming send() methodsend() is used to pass message to object . send() is an instance method of the Object class. The first argument in send() is the message that you're sending to the object - that is, the name of a method. It could be string or symbol but symbols are preferred.

What does .call do in Ruby?

The purpose of the . call method is to invoke/execute a Proc/Method instance.

What is Define_method in Ruby?

define_method is a method defined in Module class which you can use to create methods dynamically. To use define_method , you call it with the name of the new method and a block where the parameters of the block become the parameters of the new method.

What is public send?

Public Send : Invokes the method identified by symbol, passing it any arguments specified. Unlike send, public_send calls public methods only. When the method is identified by a string, the string is converted to a symbol.


1 Answers

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).

like image 186
Tamer Shlash Avatar answered Oct 24 '22 04:10

Tamer Shlash