14

as far as I understand 'send' method, this

some_object.some_method("im an argument")

is same as this

some_object.send :some_method, "im an argument"

So what is the point using 'send' method?

Leo
  • 2,061
  • 4
  • 30
  • 58
  • Because the parameter to `send` is a symbol, which can be held in a variable. E.g., `foo = :size; [].send foo`. While it can be used to access private methods, IMO its use as a generic messaging tool far outweighs its value as a way "around" the intent of a developer. – Dave Newton Feb 10 '13 at 00:47

5 Answers5

20

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.

Intrepidd
  • 19,772
  • 6
  • 55
  • 63
6

In addition to Intrepidd's use cases, it is convenient when you want to route different methods on the same receiver and/or arguments. If you have some_object, and want to do different things on it depending on what foo is, then without send, you need to write like:

case foo
when blah_blah then some_object.do_this(*some_arguments)
when whatever then some_object.do_that(*some_arguments)
...
end

but if you have send, you can write

next_method =
case foo
when blah_blah then :do_this
when whatever then :do_that
....
end
some_object.send(next_method, *some_arguments)

or

some_object.send(
  case foo
  when blah_blah then :do_this
  when whatever then :do_that
  ....
  end,
  *some_arguments
)

or by using a hash, even this:

NextMethod = {blah_blah: :do_this, whatever: :do_that, ...}
some_object.send(NextMethod[:foo], *some_arguments)
sawa
  • 165,429
  • 45
  • 277
  • 381
4

In addition to everyone else's answers, a good use case would be for iterating through methods that contain an incrementing digit.

class Something
  def attribute_0
    "foo"
  end
  def attribute_1
    "bar"
  end
  def attribute_2
    "baz"
  end
end

thing = Something.new

3.times do |x|
  puts thing.send("attribute_#{x}")
end

#=> foo
# bar
# baz

This may seem trivial, but it's occasionally helped me keep my Rails code and templates DRY. It's a very specific case, but I think it's a valid one.

Ten Bitcomb
  • 2,316
  • 1
  • 25
  • 39
  • I'd say any naming that depends on incrementing digits is a serious code smell. The above class probably wants a method like `def attributes; ["foo", "bar", "baz"]; end`. – Jezen Thomas Jan 22 '16 at 12:23
  • You are right. I was an idiot back then. But send still has its place as a metaprogramming tool, obviously. – Ten Bitcomb Jan 22 '16 at 16:54
  • 1
    To be clear: At no point did I call you an idiot, nor do I think you are one. Your example of `send` is totally valid, but hopefully the extra insight will be of use to less-experienced future readers. – Jezen Thomas Jan 22 '16 at 16:56
0

The summing briefly up what was already said by colleagues: send method is a syntax sugar for meta-programming. The example below demonstrates the case when native calls to methods are likely impossible:

class Validator
  def name
    'Mozart'
  end
  def location
    'Salzburg'
  end
end

v = Validator.new
'%name% was born in %location%'.gsub (/%(?<mthd>\w+)%/) do
  # v.send :"#{Regexp.last_match[:mthd]}"
  v.send Regexp.last_match[:mthd].to_sym
end
=> "Mozart was born in Salzburg" 
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
-1

I like this costruction

Object.get_const("Foo").send(:bar)
Peter
  • 84
  • 6