Reputation: 339
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
?
Upvotes: 12
Views: 7836
Reputation: 9523
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
).
Upvotes: 20