Decorators allow us to add behavior to objects without affecting other objects of the same class. The decorator pattern is a useful alternative to creating sub-classes.

Read more about Decorator Pattern here.

I saw a many posts about “Decorator Pattern in Ruby”, such as

and asked myself - “What is the best realization of the Decorator Pattern in Ruby?”.

I prefer to use SimpleDelegator for building an Decorators in Ruby. I think it is the best way.

You can ask me “Why do you think so?”. The main reasons to think so is - SimpleDelegator is in standard library of Ruby, It deserves respect and gives confidence for using. Everybody can care and help in improving it. It is simple, just open pull pequest in Ruby repository on GitHub. There is one pull request of mine #1454. ;)

I think you will get correct thoughts for yourself after reading the docs about SimpleDelegator in Ruby and some posts about “Decorator Pattern in Ruby”. This post only my thoughts about it. Thanks!

NOTE: Please read about the Ruby class SimpleDelegator and its parent class Delegator to understand how it works.

Example:

class User
  def initialize(first_name:, last_name:, birthday:)
    @first_name = first_name
    @last_name = last_name
    @birthday = birthday
  end

  attr_accessor :first_name, :last_name, :birthday
end
class UserDecorator < SimpleDelegator
  def full_name
    "#{first_name} #{last_name}"
  end

  def age
    # 60 * 60 * 24 * 365.25 is 31557600
    # 31557600 is one year in seconds
    ((Time.now - birthday) / 31557600).floor
  end
end
user = User.new(
  first_name: "Bogdan",
  last_name: "Denkovych",
  birthday: Time.new(1996, 6, 27, 6, 0, "+03:00")
)

user_decorator = UserDecorator.new(user)

user_decorator.class # => UserDecorator
user_decorator.first_name # => "Bogdan"
user_decorator.last_name # => "Denkovych"
user_decorator.full_name # => "Bogdan Denkovych"
user_decorator.birthday # => 1996-06-27 06:00:00 +0300
user_decorator.age # => 20