Buy my course: Security for Rails Developers.
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.
Or follow me on Twitter
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!