# Forwardable Module

Forwardable module is able to give new behaviour to an object by delegating the method to it, using `def_delegator` or `def_delegators`.

Let’s say we have this
```
class HousingUnit
  attr_reader :example

  def initialize
    @example = [:apartment, :flat, :residence]
  end
end

newhouse = HousingUnit.new
puts "This year I'm gonna get myself new #{newhouse.example.sample}!"
```

This will return `This year I'm gonna get myself new apartment!` as sample method will return random element from the array. However, it will be more readable if we have a method that can return the random element directly.

```
class HousingUnit
  attr_reader :example

  def initialize
    @example = [:apartment, :flat, :residence]
  end

  def type
    @example.sample
  end
end

newhouse = HousingUnit.new
puts "This year I'm gonna get myself new #{newhouse.type}!"
```

This will give us `This year I'm gonna get myself new residence!`. Perfect! The `HousingUnit#type` has power to access the housing unit example type.

Fast forward, Ruby provides a way to perform this kind of action by using `def_delegator`. To use it, we have to use keyword extend to add module method at class level. Then, we need to define the delegator method. The formula is
`def_delegator :an_instance, :the_delegated_method, :the_alias_method`
like this one

```
require 'forwardable'

class HousingUnit
  extend Forwardable
  attr_reader :example
  def_delegator :@example, :sample, :type

  def initialize
    @example = [:apartment, :flat, :residence]
  end

  # def type
  #   @example.sample
  # end
end

newhouse = HousingUnit.new
puts "This year I'm gonna get myself new #{newhouse.type}!" 
```

This will give us `This year I'm gonna get myself new residence!`. Note that I’m calling forwardable library here to be able to use the method.

### How about def_delegators?
In whole view it works similar like `def_delegator`. The difference is `def_delegators` able to handle multiple methods but those methods can’t have alias name of method.

```
require 'forwardable'

class HousingUnit
  extend Forwardable
  attr_reader :example
  def_delegators :@example, :sample, :size

  def initialize
    @example = [:apartment, :flat, :residence]
  end
end

newhouse = HousingUnit.new
puts "Total number of housing unit types: #{newhouse.size} "
puts "Random example of housing unit: #{newhouse.sample}"
```

This will produce
```
Total number of housing unit types: 3 
Random example of housing unit: apartment
```
