The Nil object pattern

Ruby encourages to do duck typing. Everything is an object and can send more or less messages to each other. That is why type checking is more a code smell. Very often duck typing can solve type checking. The object just behaves like expected.

Nil is special

There is an exception. In some cases the object could be NIL and the logic has to deal with it.
A Ruby on Rails example is about people having a bank account. The models:

class Person < ApplicationRecord
  has_one :bank_account
end

class BankAccount < ApplicationRecord
  has_many :transactions

  def total
    transactions.sum :value
  end

  def in_dispo?
    total.negative?
  end
end

The bank account can sum the total balance and check if the account is in dispo. Since not each person wants to have a for some reason, the presence of the account is not validated.
At first dealing with a person having a bank account is straight forward:

alice = Person.create name: 'Alice', bank_account: BankAccount.new
# Alice makes some transactions
alice.bank_account.transactions.create value: 100
alice.bank_account.transactions.create value: -4.5
alice.bank_account.total.to_s # => "95.5"
alice.bank_account.in_dispo? # => false

But for all people having no bank account, it is getting quite awkward to check for the presence of the bank account each time it has to be accessed:

bob = Person.create name: 'Bob'
if bob.bank_account.present?
  bob.bank_account.total.to_s
else
  "0.0"
end

if bob.bank_account.present?
  bob.bank_account.in_dispo?
else
  false
end

This is also a kind of type check. It is a check for Nil object.
Sure, the Delegation pattern, allowing to return nil, sometimes solves the issue. But if certain return values are expected (like 0.0 for accumulations or true/false for checking), the Nil object pattern comes in handy.

Nil object pattern

The basic idea behind the Nil object pattern is to return a default object that behaves like the expected object (in this example the bank account).
Then there is just one single point, where to check for the Nil type and then the object can receive the expected messages.
The persons bank account is either the associated bank account or the Nil object:

class Person < ApplicationRecord
  has_one :bank_account

  def bank_account
    super || NilBankAccount.new
  end
end

The class NilBankAccount:

class NilBankAccount
  def total
    0.0
  end

  def in_dispo?
    false
  end
end

By means of the Nil object, awkward Nil checks are not necessary any longer:

bob.bank_account.total.to_s # => "0.0"
bob.bank_account.in_dispo? # => false