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
set_password
method:
class User < ApplicationRecord
def set_password
self.password = SecureRandom.alphanumeric(16)
end
end
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
set_password
.
With the simple trick of returning the instance of the object from a method, you are making it chainable.
Did you enjoy reading this? Follow me on Twitter or sign up to my newsletter for more content like this!
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!