What is the difference between Ruby's send and public_send methods?
Unlike send, public_send calls public methods only.
Source
Example:
class Klass
private
def private_method
puts "Hello"
end
end
k = Klass.new
k.send(:private_method)
# => "Hello"
k.public_send(:private_method)
# => `public_send': private method `private_method' called for #<Klass:0x007f5fd7159a80> (NoMethodError)
You may want to prefer #public_send
over #send
so as not to circumvent private/protected visibility.
Ruby send vs __send__
Some classes (for example the standard library's socket class) define their own send
method which has nothing to do with Object#send
. So if you want to work with objects of any class, you need to use __send__
to be on the safe side.
Now that leaves the question, why there is send
and not just __send__
. If there were only __send__
the name send
could be used by other classes without any confusion. The reason for that is that send
existed first and only later it was realized that the name send
might also usefully be used in other contexts, so __send__
was added (that's the same thing that happened with id
and object_id
by the way).
How to use send or public_send for a 'Model' name in ruby on rails?
you want to get class name from string, something like this will work:
Object.const_get("User").all
This will throw an error if class is not found:
NameError: uninitialized constant User
If you want something that will return nil
instead of raising error, you can try:
"User".safe_constantize
What is the point of using send instead of a normal method call?
It can come in handy if you don't know in advance the name of the method, when you're doing metaprogramming for example, you can have the name of the method in a variable and pass it to the send
method.
It can also be used to call private methods, although this particular usage is not considered to be a good practice by most Ruby developers.
class Test
private
def my_private_method
puts "Yay"
end
end
t = Test.new
t.my_private_method # Error
t.send :my_private_method #Ok
You can use public_send
though to only be able to call public methods.
Ruby difference between send and instance_eval?
From the fine manual:
send(symbol [, args...]) → obj
send(string [, args...]) → objInvokes the method identified by symbol, passing it any arguments specified. [...] When the method is identified by a string, the string is converted to a symbol.
and for instance_eval
:
instance_eval(string [, filename [, lineno]] ) → obj
instance_eval {| | block } → objEvaluates a string containing Ruby source code, or the given block, within the context of the receiver (obj). In order to set the context, the variable
self
is set to obj while the code is executing, giving the code access to obj’s instance variables.
So send
executes a method whereas instance_eval
executes an arbitrary block of code (as a string or block) with self
set to the object that you're calling instance_eval
on.
In your case, there isn't much difference as the string you're handing to instance_eval
is just a single method. The main difference is that anyone reading your code (including you in six months) will be wondering why you're using instance_eval
to call a single method.
You might also be interested in Object#public_send
and BasicObject#__send__
What does send() do in Ruby?
send
sends a message to an object instance and its ancestors in class hierarchy until some method reacts (because its name matches the first argument).
Practically speaking, those lines are equivalent:
1.send '+', 2
1.+(2)
1 + 2
Note that send
bypasses visibility checks, so that you can call private methods, too (useful for unit testing).
If there is really no variable before send, that means that the global Object is used:
send :to_s # "main"
send :class # Object
Ruby nested send
You can use instance_eval
:
obj.instance_eval("foo.bar")
You can even access the instance variable directly:
obj.instance_eval("@foo.bar")
Related Topics
Verb-Agnostic Matching in Sinatra
How to Run Ruby 2.0 with Jruby 1.7
Jruby: Import VS Include VS Java_Import VS Include_Class
How to Find a Model's Relationships
Using the Value of a Variable as Another Variables Name in Ruby
Rails Implementation of Search with Autocomplete
Strictly Convert String to Integer (Or Nil)
Ruby on Rails: How to Check If a File Is an Image
How to Validate the Presence of a Belongs to Association with Rails
How to Install Ruby 1.9.3 on Ubuntu Without Rvm
Differencebetween #Encode and #Force_Encoding in Ruby
Normalizing Line Endings in Ruby
Weird Rails Error "Permission Denied: Bin/Rails" for Old Rails Apps
Adding a Submit Button Image to a Rails Form
Ruby: No Such File or Directory @ Rb_Sysopen - Testfile (Errno::Enoent)