What does send() do in Ruby?

Solution 1:

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

Solution 2:

send is a ruby (without rails) method allowing to invoke another method by name.

From documentation

   class Klass
     def hello(*args)
       "Hello " + args.join(' ')
     end
   end
   k = Klass.new
   k.send :hello, "gentle", "readers"   #=> "Hello gentle readers"

http://corelib.rubyonrails.org/classes/Object.html#M001077

Solution 3:

One of the most useful feature I think with .send method is that it can dynamically call on method. This can save you a lot of typing. One of the most popular use of .send method is to assign attributes dynamically. For example:

class Car
  attr_accessor :make, :model, :year
end  

To assign attributes regularly one would need to

c = Car.new
c.make="Honda"
c.model="CRV"
c.year="2014"

Or using .send method:

c.send("make=", "Honda")
c.send("model=", "CRV")
c.send("year=","2014")

But it can all be replaced with the following:

Assuming your Rails app needs to assign attributes to your car class from user input, you can do

c = Car.new()
params.each do |key, value|
  c.send("#{key}=", value)
end

Solution 4:

Another example, similar to Antonio Jha's https://stackoverflow.com/a/26193804/1897857

is if you need to read attributes on an object.

For example, if you have an array of strings, if you try to iterate through them and call them on your object, it won't work.

atts = ['name', 'description']
@project = Project.first
atts.each do |a|
  puts @project.a
end
# => NoMethodError: undefined method `a'

However, you can send the strings to the object:

atts = ['name', 'description']
@project = Project.first
atts.each do |a|
  puts @project.send(a)
end
# => Vandalay Project
# => A very important project