Search code examples
rubymethodschain

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?


Solution

  • 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| self.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)