Ruby’s Object#send allows dynamic calling of a method. This is very useful, but what if we wanted to call several levels deep on an object? For instance:
# Normal call chain post.comments.first.commented_at # Dynamically with send? Have to call three times. post.send(:comments).send(:first).send(:commented_at)
What if the number of calls to send is variable depending on what we’re trying to show? In one case we might need post.posted_at for the date, and in another case we might need post.comments.first.commented_at for the date.
How could we dynamically craft the definition of the methods to send if we don’t know how many calls to Object#send we’ll have? We need a way to define an arbitrary number of method calls.
Behold, a recursive send: Object#rsend
class Object def rsend(*args, &block) obj = self args.each do |a| b = (a.is_a?(Array) && a.last.is_a?(Proc) ? a.pop : block) obj = obj.__send__(*a, &b) end obj end alias_method :__rsend__, :rsend end
Each argument passed to Object#rsend is an array with the symbols and arguments that will be passed on to Object#send:
post.rsend([:comments],[:first],[:commented_at])
If there are no arguments to be passed on to send, the array brackets can be omitted:
post.rsend(:comments, :first, :commented_at)
Of course, in practice you’ll probably be defining your method call chain in one part of your code, putting it in a variable, and sending it to rsend with a splat*:
the_date = [:comments, :first, :commented_at] #...somewhere else in your code you've passed the_date along: post.rsend(*the_date)
With arguments:
a = [0,1,2,3,4,5,6,7,8,9] a.rsend([:slice, 2, 8]) #=> [2, 3, 4, 5, 6, 7, 8, 9] a.rsend([:slice, 2, 8], [:slice, 1, 3]) #=> [3, 4, 5]
Object#send accepts a block. What about blocks? Pass in a proc:
a.rsend([:map, (proc { |x| x*2 })]) #=> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] a.rsend([:map, (proc { |x| x*2 })], [:select, (proc { |x| x % 4 == 0})]) #=> [0, 4, 8, 12, 16]
And, in an effort to make Object#rsend behave like Object#send for the simple case, you can send a regular block:
a.rsend(:map) { |x| x*2 } #=> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Caveat: For the case needing parameters, Object#rsend does require an array, so:
a.rsend(:slice, 2, 8) # wrong, does not work like Object#send a.rsend([:slice, 2, 8]) # right
A quirk that I’ve left in for fun, but it might (and maybe should) change: If providing a single block, that block will be called on every call unless you’ve already passed in a proc:
a.rsend(:map, :map) { |x| x*2 } #=> [0, 4, 8, 12, 16, 20, 24, 28, 32, 36] a.rsend(:map, [:map, (proc { |x| x+5 })], :map) { |x| x*2 } #=> [10, 14, 18, 22, 26, 30, 34, 38, 42, 46] #outer block was called on first and third :map
Can anyone come up with a good use for this call-the-block-each-time behavior?
Has anyone done this already? I searched for such a thing and came up empty. Maybe this method should be called something else? I named it based on each call recursing down the chain of methods with a new object being returned for the next method to be sent to.
Suggestions and comments are welcome.

