Develop the right mindset for Rails security
Avoid shipping vulnerable code by learning how to prevent security issues in your Rails applications.
Get the course for $99One 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
endset_password method:
class User < ApplicationRecord
def set_password
self.password = SecureRandom.alphanumeric(16)
end
endUser.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
endset_password.
With the simple trick of returning the instance of the object from a method, you are making it chainable.