Explaining magic behind popular Ruby on Rails code

This article is a continuation of a popular article about the magic behind the popular Ruby code. This time, I will explain the logic behind popular Ruby on Rails code used by thousands of developers worldwide but not available out of the box in pure Ruby.

Checking for presence

I would risk writing that the most popular Rails’ methods are present? and blank?. Along with .presence, they are used to verify if a given thing (variable, object, attribute) has any value. They are universal and work with every type of value, and under the hood, they are straightforward.

I sometimes ask developers if those methods are part of the core Ruby, and they are often surprised that they are only implemented in Rails.


This method ends with the quotation mark because it always returns a boolean value: true or false. As I mentioned before, the logic for it is elementary. Let's take a closer look at the blank? source code for different objects type.


def blank?
  respond_to?(:empty?) ? !!empty? : !self

The above definition is very flexible as Ruby objects like arrays, hashes, and strings implement empty? method but you can also use duck typing and implement this method in your classes:

class Garage
  delegate :empty?, to: :@cars
  def initialize
    @cars = []

  def park_car(car)
    @cars << car

you can test it when no cars are parked inside the garage and when you would park one car:

garage = Garage.new
garage.blank? # => true

garage.blank? # => false


Even though the string implements the empty? method, it is not always recommended to use that method. It won’t work if the string contains white spaces; that’s why Rails implements the blank? method for strings a little bit different:

def blank?
  empty? ||
      !!/\A[[:space:]]*\z/.match(self, 0)
    rescue Encoding::CompatibilityError

Because the regexp is expensive, empty? is used in the first place, and it is enough in most cases where the string does not contain anything.


For integers blank? will always return false:

def blank?

Other objects

Rails implements the blank? method for other objects as well including:

  • ActiveRecord relation and errors
  • Database configurations
  • TimeWithZone, Time, Date, and DateTime

The method definitions are straightforward; usually, they return false or are delegation to a different method, so there is no need to show their sources.


This method is just a simple inversion of blank? method for different objects:

def present?


Before I show you the source of this method, let’s take a look at a simple example to understand why you need to use it:

class User < ApplicationRecord
  def full_address
    return address.full_address if address.full_address.present?

    "No location"

The above method is quite simple, but we can make it a one-liner with presence:

class User < ApplicationRecord
  def full_address
    address.full_address.presence || "No location"

When the value is present, the method returns the value; otherwise, it returns nil; that’s why the additional value is returned. Let’s take a look at the method’s source:

def presence
  self if present?

Again, the source code is simple, but it will work perfectly with any type of object.

Manipulating dates with 1.day, 2.months.ago, etc.

Rails makes it easy to manipulate dates by providing an interface with more human-readable values:

  • 1.second
  • 1.minute
  • 1.hour
  • 1.day
  • 1.week
  • 1.month
  • 1.year

With pure Ruby, to add 5 hours to the current time, you would have to do the following:

Time.now + (60 * 60 * 5)

while with Rails, you can simply do:

Time.now + 5.hours

This is perfectly simple and readable at the same time. Let’s take a closer look under the hood of that expression.

Active Support’s Duration

The class responsible for the mentioned logic is ActiveSupport::Duration. Those two calls return the same value:

ActiveSupport::Duration.new(60, seconds: 60)

The first argument is the time representation in seconds, and the second is a key argument where the key is the name of units, and the value is the number of seconds, hours, days, etc.

Since Rails extends the numeric classes, methods like days, months, etc., are available on the standard integer or float. You can replicate that behavior by opening the Integer class and adding some custom logic:

class Car; end

class Integer
  def cars
    Array.new(self) { Car.new }

Now, if we would like to create two cars, we can do the following:

2.cars # => [#<Car:0x00007ff2b01cae80>, #<Car:0x00007ff2b01cae58>]

Some time ago

With Rails, we can get the past date with the following call:


Since we know what the logic sits behind 6.hours, we can now take a look at the ago method. This method uses another Active Support module called TimeWithZone.

The method since is called which accepts the number of seconds and returns a time in past or future. If the number of seconds is negative, it will return the time in the past:

# the same as
Time.current.since(-1 * (60 * 60))

# the same as
Time.current.since(60 * 60)

Addition and subtraction

One thing has left to explain in terms of playing with dates with the help of Rails. You can usually spot the following pattern in many applications:

Time.at(value) + 5.hours

So what happens if you would like to increase a time value by the given number of hours? Since + is just a method invoked on a Time instance, we can check where the method is defined by executing the following code:


Again, ActiveSupport overwrote the default method, so it’s possible to pass ActiveSupport::Duration as the argument. In pure Ruby, you are limited to the Time instance. Let’s check the definition as it’s a tricky one and not obvious when you look at it for the first time:

def plus_with_duration(other) #:nodoc:
  if ActiveSupport::Duration === other

alias_method :plus_without_duration, :+
alias_method :+, :plus_with_duration

When you call +, the plus_with_duration method is called. When the argument is the instance of ActiveSupport::Duration, then the since method is called, which we discussed before. Otherwise, the plus_without_duration method is called, which is an alias for +, so the standard method for Time is executed.

Thanks to this trick, we can support both Duration instance and Time instance as the argument.


Delegation is a simple process of executing methods on a given class executed with a different object that lives inside the object’s instance on which the method is executed. This description sounds a little bit complicated so let’s consider the following example:

class Profile
  def image_url

  def nickname

class User
  def initialize
    @profile = Profile.new

  def image_url

  def nickname

user = User.new
user.nickname # => 'nick'
user.image_url # => 'image_url'

This the explicit delegation as we explicitly use other object and call the desired method on it. If we would like to delegate more methods, we can easily repeat ourselves and make the class definition longer and longer.

Ruby standard delegation

Core Ruby provides a way to delegate methods as well:

require 'forwardable'

class User
  extend Forwardable

  def initialize
    @profile = Profile.new

  def_delegators :@profile, :nickname, :image_url

You have to remember to extend your class with the Forwardable module; otherwise, you won’t be able to use the def_delegators method. Let’s take a look at the alternative delegation provided by Rails.

Rails delegation

If you are using Rails, you can delegate the methods using the following way:

class User
  delegate :nickname, :image_url, to: :@profile

  def initialize
    @profile = Profile.new

How it’s implemented in Rails? Let’s find the source of the method first:


Again, it’s ActiveSupport module and its core extension for module:

def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
  # definition

As you can see the Rails’ delegation is way more flexible as you can achieve the following things.

Add prefix

We can simply use a prefix to make the delegation more explicit:

class User
  delegate :nickname, to: :@profile, prefix: :profile

User.new.profile_nickname # => 'nick'

Allow for nil values

class User
  delegate :nickname, to: :@profile, allow_nil: true

  def initialize
    @profile = nil

User.new.nickname # => nil

Make the delegation private

If you would to delegate methods but make them private, you can add the private option:

class User
  delegate :nickname, to: :@profile, private: true

If you would call now User.new.nickname, you would receive NoMethodError as the error is only available inside the class, and to invoke it inside, you have to use send - User.new.send(:nickname).

Explaining magic behind delegate from Rails

Investigation time. The way the delegation is working in Rails is simple and may be a bit surprising for you. If you are calling the following delegation:

delegate :nickname, to: :@profile, allow_nil: true, prefix: :profile

then the Rails is building the following definition as a text (and repeat it for every delegated method):

def profile_nickname
  _ = @profile
  if !_.nil? || nil.respond_to?(:nickname)

then the Rails finds the place where the method should be defined by calling a method from the Thread::Backtrace::Location module provided by pure Ruby:

location = caller_locations(1, 1).first
path = location.path
line = location.lineno

and then uses the module_eval method to execute the string in the context of the module:

module_eval(method_def.join(";"), file, line)

The method_def variable is an array with methods definition. The file and line arguments are passed, but they are used only for error messages.

That’s it.