# Modules, Mixins and Namespaces — Ruby

Source: https://www.geekswithgeeks.com/en/ruby/o-modules

> Share behaviour with modules using include, extend and prepend, and organise code with namespaces.

## Ruby's answer to multiple inheritance

A **module** is a collection of methods and constants that cannot be instantiated. Modules serve two purposes. As **namespaces**, they group related classes and avoid name clashes: `Billing::Invoice` versus `Shipping::Invoice`. As **mixins**, they share behaviour across unrelated classes. **`include`** adds a module's methods as instance methods (the module is inserted into the class's ancestor chain just above the class); **`extend`** adds them as singleton methods on an object or class (class-level methods); and **`prepend`** inserts the module **before** the class, so its methods run first and can call `super` to reach the class's own method, which is useful for wrapping behaviour such as logging or caching. Ruby's own **`Enumerable`** and **`Comparable`** are mixins: define `each` and include Enumerable to get `map`, `select`, `sort` and dozens more; define `<=>` and include Comparable to get comparison operators. `ClassName.ancestors` shows the **method lookup chain**, which explains which method actually runs.

## Mixins in practice

Enumerable from one each method, Comparable from <=>, and prepend for wrapping.

```ruby
module Billing
  class Money
    include Comparable
    attr_reader :paise

    def initialize(paise) = @paise = paise
    def <=>(other) = paise <=> other.paise          # gives <, >, ==, between?, clamp
    def to_s = format("Rs %.2f", paise / 100.0)
  end

  class Cart
    include Enumerable

    def initialize = @items = []
    def add(name, money) = (@items << [name, money]; self)
    def each(&block) = @items.each(&block)            # Enumerable needs only each
  end
end

module Audited
  def mark_paid!(*args)
    puts "audit: marking #{number} as paid"
    super                                            # bare super forwards args to Invoice#mark_paid!
  end
end
Invoice.prepend(Audited)

cart = Billing::Cart.new.add("pen", Billing::Money.new(4950)).add("ink", Billing::Money.new(19900))
puts cart.max_by { |_, m| m }.first                    # ink
puts cart.sort_by { |_, m| m }.map(&:first).inspect    # ["pen", "ink"]
puts Invoice.ancestors.first(3).inspect                 # [Audited, Invoice, Object]
```

## Skills on a CV

A class inherits from one parent, like a family name, but can include many modules, like skills on a CV: "can be compared", "can be listed and sorted", "is audited". Any class can pick up the same skill.

**Quiz:** What do you need to define to gain Enumerable methods such as map and select in your class?

- [ ] to_s
- [ ] <=>
- [ ] initialize only
- [x] each

*Answer:* each. Enumerable builds all its methods on top of each.
