A Guide to Method Chaining

Share this article

method_chaining
Method chaining is a very handy technique for invoking multiple methods at once. Not only does it improve the readability of the code, but it also reduces the amount of code needed when interacting with a class or an instance of a class. You have probably already interacted with method chaining in one way or another, especially if you have used ActiveRecord. Remember doing something like this Model.where(…).order(…)? Yep, that is method chaining. In this article you will learn how to apply the same features to your own code. This article will be divided into two simple parts:
  • Introduction to method chaining
  • Method chaining at the class level
The first part will cover the basics of method chaining, with step-by-step examples; and the second part will explain how to do method chaining at the class level, be it via explicit method declaration of class methods or by using and extending an additional module. Are you ready to embark into this awesome journey? Let’s go!

Introduction to Method Chaining

For the introductory part we are going to be designing a class that will contain a few methods that can be eventually chained together, and one method that outputs a message. Let us start with our basic class structure:
class Person

  def name(value)
  end

  def age(value)
  end

  def introduce
  end

end
Nothing much here but this will serve as the base for this example. As you can see, it contains three methods: name(), which will take an input value; age(), which also takes an input value; introduce, it will not take an input value. With this basic information at hand, let us implement the next step. We are now going to store the input values for name() and age() in instance variables so that we can access them later down the road:
# ...
def name(value)
  @name = value
end

def age(value)
  @age = value
end
# ...
Great, with this addition to our methods, let us try method chaining and see what happens:
> person = Person.new
# => #<Person:0x007fb18ba29cb8>
> person.name('Baz')
# => "Baz"
> person.name('Baz').age(21)
NoMethodError: undefined method `age' for "Baz":String
As expected, it does not work. The reason being is because the methods are just returning a value – a string in this case. We need to modify our methods once again, and this time, we are going to be returning something else: self. By returning self we are allowing instance methods to be chained together, just like that! Easy huh?! Okay, it is time to modify our methods again:
# ...
def name(value)
  @name = value
  self
end

def age(value)
  @age = value
  self
end
# ...
Fantastic, what will happen if we try to chain our method calls?
> person = Person.new
# => #<Person:0x007ff202829e38>
> person.name('Baz')
# => #<Person:0x007ff202829e38 @name="Baz">
> person.name('Baz').age(21)
# => #<Person:0x007ff202829e38 @name="Baz", @age=21>
It worked! Congratulations, you have just implemented method chaining in Ruby! Now, we need to modify our introduce method and have it do something:
# ...
def introduce
  puts "Hello, my name is #{@name}, and I am #{@age} years old."
end
# ...
With all of our code in place, what do you think will happen when we call introduce in our method chain?
> person = Person.new
# => #<Person:0x007fd079085ba0>
> person.name('Baz').age(21).introduce
# => Hello, my name is Baz and I am 21 years old.
Yep, it worked as expected. Notice that the introduce method needs to be at the end of the chain because it does not return an instance of self. Here is the complete code for this example, which I have also contributed to Wikipedia under the Method chaining article:
class Person

  def name(value)
    @name = value
    self
  end

  def age(value)
    @age = value
    self
  end

  def introduce
    puts "Hello, my name is #{@name} and I am #{@age} years old."
  end

end
As an exercise for the reader, I encourage you to modify the introduce method and make it output the text based on the data available. For example, if only @name is available, you would print the sentence without the age part. If only @age is available, you would print the sentence without the name part.

Method Chaining at the Class Level

We have just learned how to chain our method calls when invoking methods on an instance of a class. But what about chaining the methods at the class level, similar to Model.where(…).order(…)
? It is pretty much the same process, except that our method declaration will be at the class level instead of the instance level. Let us go ahead and do just that, let us design a class that contains class methods that can be chained together. The basic structure for this example will be something like this:
class Speaker
  class << self

    def say(what)
      @say = what
      self
    end

    def drink(what)
      @drink = what
      self
    end

    def output
      "The speaker drinks #{@drink} and says #{@say}"
    end

  end
end
Pretty simple, right? Notice that all of these three methods are class methods. I could have declared them individually with def self.say()… but for multiple declaration of class methods I feel that it is more concise to have a single class << self declaration and declare all of the class methods inside of it. Great, let us play with it now:
> Speaker.say('hello').drink('water').output
# => The speaker drinks water and says hello
And there you have it, worked like a charm. Another way to accomplish this without having to explicitly declare the class methods would be to use a module and extend it in our class. By doing this we expose the methods in the module as class methods in our Speaker class:
module SpeakerClassMethods
  def say(what)
    @say = what
    self
  end

  def drink(what)
    @drink = what
    self
  end

  def output
    "The speaker drinks #{@drink} and says #{@say}"
  end
end

class Speaker
  extend SpeakerClassMethods
end
And it should work exactly as having explicitly declared the class methods:
> Speaker.say('hello').drink('water').output
# => The speaker drinks water and says hello
Great, it worked. As another exercise for the reader, I encourage you to modify the output method and make it output the text based on the data available, similar to the previously suggested exercise for the reader.

Conclusion

This article has demonstrated how simple and easy it is to incorporate method chaining in Ruby, be it at the instance level or the class level. It also showed the different ways that we can accomplish the same results by using different techniques when adding class-level method chaining. And I hope that it has provided you with enough information for you to be able to apply the same techniques to your own code.

Frequently Asked Questions (FAQs) about Method Chaining in Ruby

What is the concept of method chaining in Ruby?

Method chaining in Ruby is a powerful programming technique that allows you to call multiple methods on the same object in a single line of code. This is possible because each method call in Ruby returns an object, and you can immediately call another method on that object. This technique can make your code more concise and readable, especially when performing a series of transformations on a data object.

How does method chaining work in Ruby?

In Ruby, method chaining works by calling a method on an object and then immediately calling another method on the result. This is possible because every method in Ruby returns an object. For example, you might call a method to select certain elements from an array, and then immediately call another method to sort those elements. This would look something like array.select {...}.sort.

What are the benefits of method chaining in Ruby?

Method chaining in Ruby can make your code more concise and easier to read. Instead of writing multiple lines of code to perform a series of operations on an object, you can accomplish the same task in a single line. This can make your code more efficient and easier to maintain. Additionally, method chaining can help you write more declarative code, which describes what the code does, rather than how it does it.

Are there any drawbacks to method chaining in Ruby?

While method chaining can make your code more concise, it can also make it more difficult to debug if something goes wrong. If an error occurs in a chain of methods, it can be challenging to determine which method caused the error. Additionally, method chaining can sometimes lead to less readable code if overused. It’s important to strike a balance between conciseness and readability.

Can you provide an example of method chaining in Ruby?

Sure, here’s a simple example of method chaining in Ruby. Let’s say you have an array of numbers and you want to select the even numbers and then sort them in descending order. You could do this with method chaining like so:

numbers = [1, 2, 3, 4, 5, 6]
sorted_evens = numbers.select {|n| n.even?}.sort.reverse

In this example, the select method is called on the numbers array to select the even numbers. The sort method is then called on the result to sort the numbers, and finally the reverse method is called to sort the numbers in descending order.

Can all methods be chained in Ruby?

In Ruby, you can chain any methods that return an object. However, not all methods return an object. Some methods, like puts and print, return nil, and you cannot call methods on nil. If you try to chain a method that returns nil, you will get a NoMethodError.

How can I debug a chain of methods in Ruby?

Debugging a chain of methods in Ruby can be challenging, but there are a few strategies you can use. One approach is to break the chain into separate lines of code and inspect the return value of each method. Another approach is to use the tap method, which allows you to inspect an object in the middle of a method chain without breaking the chain.

Can method chaining be used with custom methods in Ruby?

Yes, you can use method chaining with custom methods in Ruby, as long as those methods return an object. When you define a custom method, you can choose what it returns. If you want to be able to chain your custom method with other methods, you should ensure that it returns an object.

How does method chaining relate to the principle of “command-query separation” in Ruby?

The principle of command-query separation in programming suggests that a method should either perform an action (a command) or return a value (a query), but not both. In Ruby, however, it’s common for methods to both perform an action and return a value, which enables method chaining. When you chain methods in Ruby, each method in the chain performs an action and then returns a value that the next method in the chain can act upon.

Is method chaining a common practice in Ruby?

Yes, method chaining is a common practice in Ruby. It’s often used in Ruby on Rails, a popular Ruby framework for web development. However, like any programming technique, it should be used judiciously. While method chaining can make your code more concise, overusing it can make your code harder to read and debug.

Thiago JackiwThiago Jackiw
View Author

Thiago Jackiw is a well-rounded Engineering Manager / Senior Software Engineer and Entrepreneur who enjoys exploring new technologies. He has been working with Ruby since 2006 and currently lives in the San Francisco Bay Area. You should follow him on Twitter, and check his latest open source projects on GitHub.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week