B A B A - 14 days ago 5
Ruby Question

How to chain methods in ruby passing the output of one method to consecutive methods

How can I pass the results of a method to another method in ruby?
eg:

class D
def initialize(text)
@text = text
end

def a s
"hello #{s}"
end

def b s
"hi #{s}"
end
end


So, what I want to do is pass the output of method a to method b. So essentially(if the methods aren't inside a class) I can do the following the following:

puts b(a "Tom") #=>hi hello Tom


However, even if this isn't inside a class, it wouldn't look good if there are a lot of methods so there must be a more elegant way to do this. So what is the proper way to get the output
hi hello Tom
by applying the methods a and b to an instance of the class D?

UPDATE
I just wanted to make it a little bit more clear. Eg, in F# you can do something like this:

let a s = "hello " + s
let b s = "hi " + s
"Tom" |> a |> b #=> hello hi Tom


Here we defined functions a and b and then passed on the results to the next function.
I know that its a functional language so ways of doing things would be different there. But I am just wondering if there are any such tricks in Ruby?

Answer

You can leave the ()

def a s
  "hello #{s}"
end

def b s
  "hi #{s}"
end

puts b a "Tom"

If you have many methods :

puts [:a,:b].inject("Tom"){|result,method| Object.send(method,result)}

If you want to use those methods with any object (including Classes) :

module Kernel
  def chain_methods(start_value, *methods)
    methods.inject(start_value){|result,method| self.send(method,result)}
  end
end

class D
  def a s
    "hello #{s}"
  end

  def b s
    "hi #{s}"
  end
end

class E
  class << self
    def a s
      "hello #{s}"
    end

    def b s
      "hi #{s}"
    end
  end
end


# Example with instance methods
puts D.new.chain_methods("Tom", :a, :b)

# Example with class methods
puts E.chain_methods("Tom", :a, :b)

# Thanks mudasobwa :
E.chain_methods("Tom", :a, :b, :puts)