Method chaining in Ruby

08 Jun 2022

One of Ruby's great features is method chaining. For instance, Active Record heavily relies on this and method chaining enables us to do cool things like User.where("active = 1").count or 1.day.ago.

Have you ever wondered about how is that possible? Let's look into it, it is pretty simple.

Let's use a simple example of having a user model and you want to be able to set a default password for your user when they signup via OAuth. So you want to be able to do something like this in your controller:

class OmniauthCallbacksController < ApplicationController
  def provider
    auth = request.env['omniauth.auth']
    user = User.find_or_create(provider: auth.provider, email: auth.email, uid: auth.uid)
    user.set_password.save! unless user.persisted?
    ...
  end
end
Then in your model you would implement the set_password method:
class User < ApplicationRecord
  def set_password
    self.password = SecureRandom.alphanumeric(16)
  end
end
If you you try User.new.set_password.save! it will fail with a NoMethodError, because set_password returns a string, but the save method is implemented on User.
I bet now you figured out how to make this work. It is pretty simple, you just need to return the user instance from set_password:
class User < ApplicationRecord
  def set_password
    self.password = SecureRandom.alphanumeric(16)
    self
  end
end
And voila, now you can chain any method after set_password.
With the simple trick of returning the instance of the object from a method, you are making it chainable.

I run an indie startup providing vulnerability scanning for your Ruby on Rails app. It is free to use at the moment, and I am grateful for any feedback about it.
If you would like to give it a spin, you can do it here: Vulnerability Scanning for your Ruby on Rails app!

Did you enjoy reading this? Follow me on Twitter or sign up to my newsletter for more content like this!

Related posts