Ruby `send` vs `call` method
To begin with, send
and call
are two very different methods.
In ruby, the concept of object orientation takes its roots from Smalltalk. Basically, when you call a method, you are sending that object a message. So, it makes sense that when you want to dynamically call a method on an object, the method you call is send
. This method has existed in ruby since at least 1.8.7.
In ruby, we also have a concept of "blocks". Blocks are the do...end
things attached to the end of method calls. Blocks can be traditionally yield
ed to; or, it is entirely possible to create an object out of a block (a Proc
), and pass that around. In order to execute the block, you can call call
on the block.
call
has never been defined on Object
, whereas send
is defined on everything.
(note: for some reason, call
doesn't seem to have documentation in the 2.3.0 documentation; however, it still exists and does the same thing from 2.2.0, so I linked that one instead.)
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 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).
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 method call, element.send(), throws ArgumentError
Calling the method this way works.In your example,What is wrong with thevalue = method(element)
element.send(method)
syntax?
element
is an integer, and method
is a symbol, e.g. 1
and :method
.So value = method(element)
is equivalent to:
value = method(1)
whereas value = element.send(method)
is equivalent to:value = 1.send(:method)
which is basically:value = 1.method
It should be obvious that method(1)
and 1.method
is not the same. When can I safely call send method on objects in Ruby?
TLDR;
Calling send is fine, it's inside your class.
Full Explanation
Alex, Here is what I have always thought about this tactic. I believe that this is well inline with the community.
The Ruby Docs say this about send:
This is a public method accessible to anyone in the world. That means anyone using your code can call private functions whenever they want!Invokes the method identified by symbol, passing it any arguments specified. You can use
__send__
if the name send clashes with an existing method in obj.
Thus... you shouldn't really think in terms of public and private functions as you would in other languages. I would argue you change your definitions a little bit.
I don't have some big rationale for this, just an overall impression about how these concepts work in Ruby.Public: Well-tested, robust, error-checked functions which are recommended for use by the world.
Private: Helper functions which may accept invalid input and break things.
For your specific problem its important to remember that you are the one coding this up, and I assume that your code is within a class you created. In that case, I use send
all the time! It's shorted than public_send
and I know exactly what I'm calling!
You will want to document it well enough so that anyone coming behind you will know what to be careful of.
Related Topics
Strong Parameters with Nested Hash
Difference Between "Class A; Class B" and "Class A::B"
How to Handle 404 Errors with Ruby Http::Net
Error Generating Source Map - Grunt and SASS Configuration
Asynchronously Iterating Over The Response of a Request Using Thin and Sinatra
Binding to Networking Interfaces in Ruby
Dbi::Interfaceerror: Could Not Load Driver (Uninitialized Constant MySQL error)
Extend Model in Plugin with "Has_Many" Using a Module
How to Silence The Call to a Rails Controller's Action All Together
How to Find Out What Is Intercepting 'Method_Missing'
Watir Changing Mozilla Firefox Preferences
Securely Display an Image Uploaded with Paperclip Gem
Ubuntu 10 Ruby 1.9 Rails 3: No Such File or Directory