Method delegation is a technique in which when we call a method, it calls another method in the background. It’s like:

A  calls B and in return B calls  C

Method delegation technique helps in reducing the complexity in cases when we have one object obj1 inside another object obj2. Now if we want to call something on obj1, we need to write:

obj2.obj1.somemethod()

With the help of method delegation, we can write:

obj2.somemethod()

which makes the statement more readable and less complex.

Let us check a simple example.

In this example, we have a Student object that have Address object as its member.

class Student

  attr_accessor :name, :gender, :address       # allow us to read these fields

  def initialize(name, gender, address)
    @name = name
    @gender = gender
    @address = address
  end
end

class Address
  
  attr_accessor :zip, :city, :state, :country

  def initialize(zip, city, state, country)
    @zip = zip
    @city = city
    @state = state
    @country = country
  end
end

ashutosh = Student.new('Ashutosh Pandey', 'Male', Address.new('111111', 'New Delhi', 'Delhi', 'Country'))

puts ashutosh.name
puts ashutosh.address.city
puts ashutosh.address.country

Now, it would be better if we can call the city, state, country etc. of the Student’s address object like this:

ashutosh.city

instead of

ashutosh.address.city

To achieve this, we will use method delegation technique of Ruby. We will be using the forwardable library provided by Ruby.

Here is the updated example:

require 'forwardable'

class Student
  extend Forwardable

  attr_accessor :name, :gender, :address

  def_delegators :@address, :zip, :city, :state, :country

  def initialize(name, gender, address)
    @name = name
    @gender = gender
    @address = address
  end
end

class Address

  attr_accessor :zip, :city, :state, :country

  def initialize(zip, city, state, country)
    @zip = zip
    @city = city
    @state = state
    @country = country
  end
end

ashutosh = Student.new('Ashutosh Pandey', 'Male', Address.new('111111', 'New Delhi', 'Delhi', 'Country'))

puts ashutosh.name
puts ashutosh.city
puts ashutosh.country

By using def_delegators, we are telling Student class to delegate any call to zip, city, state, country to the current address object. Hence,

ashutosh.name => delegated internally to => ashutosh.address.name