Delegation

What is Delegation?

In plain English, when you delegate something to someone else, you divide up responsibilities amongst yourselves.

Intent

Attach additional responsibilities to an object dynamically.

Some simple examples

Packing a bunch of functionality into a single object’s class and instance methods.

class Product
  def sku
    # Returns a sku specific to a
    # particular instance of a product.
  end
end

class Book < Product
  def author
    # Returns an Author object
    # associated with that book.
  end
end

book = Book.new
book.sku #sku
class Report
  def records
    [1, 2, 3, 4, 5]
  end

  def print
    p "Game of Thrones S07E07's script got leaked"
  end
end

class InTriplicateReport < Report
  def records
    record = super
    record * 3
  end

  def print
    super
    super
    super
  end
end

report = InTriplicateReport.new
p report.records
report.print

5 Patterns of Delegation

1. Explicitly

Any time you use another object to perform logic instead of keeping it within the class itself, you are delegating

2. Delegation with method_missing

3. Delegate

by Active Support

require 'active_support/core_ext/module/delegation'

class LazyEmployee
  def initialize(sandwich_maker)
    @sandwich_maker = sandwich_maker
  end
  
  delegate :make_me_a_sandwich, to: :sandwich_maker
  
  private
  attr_reader :sandwich_maker
end

4. Delegate

by SimpleDelegator class

class User
  def born_on
    Date.new(1989, 9, 10)
  end
end

class UserDecorator < SimpleDelegator
  def birth_year
    born_on.year
  end
end

A concrete implementation of Delegator, this class provides the means to delegate all supported method calls to the object passed into the constructor and even to change the object being delegated to at a later time with #__setobj__ - RubyDoc

5. Using Forwardable

The Forwardable module provides delegation of specified methods to a designated object, using the methods def_delegator and def_delegators.

class Book
  def language
    "English"
  end

  def year
    "1926"
  end

  def author
    "Ernest Hemingway"
  end

  def title
    "The Sun Also Rises"
  end
end

class Product
  def initialize
    @book = Book.new
  end

  def language
    @book.language
  end

  def year
    @book.year
  end

  def author
    @book.author
  end

  def info
    @book.title
  end
end

Ugh!

Lets use forwadable

Resources

  • https://robots.thoughtbot.com/evaluating-alternative-decorator-implementations-in
  • http://ruby-doc.org/
  • https://blog.lelonek.me/how-to-delegate-methods-in-ruby-a7a71b077d99
  • vaidehijoshi.github.io/blog/2015/03/31/delegating-all-of-the-things-with-ruby-forwardable

How to delegate methods in ruby

By Ahmad Hamza

How to delegate methods in ruby

Describing all delegation patterns in ruby

  • 572