liveBook · Manning

Comparable

As explained in The Well-Grounded Rubyist, Fourth Edition

Comparable is a Ruby module that provides comparison-based methods to classes whose objects define a comparison operation.

Suppose two bids should be ordered by their estimated prices. Include `Comparable` in the class and define an instance method named `<=>` that compares one bid with another. Ruby can then use that method to provide operators such as `<`, `>`, and `==`. section 7.6.2

Listing 7.2 Example of a class that mixes in the Comparable module
class Bid
  include Comparable
  attr_accessor :estimate
  def <=>(other_bid)                            1
    if self.estimate < other_bid.estimate
      -1
    elsif self.estimate > other_bid.estimate
      1
    else
      0
    end
  end
end

The `Bid` class returns a negative number when its estimate is lower, zero when the estimates match, and a positive number when its estimate is higher. That three-way result is the basis for the comparison methods supplied by `Comparable`. section 7.6.2

When the value being compared already has `<=>`, the method can be much shorter: `def <=>(other_bid); estimate <=> other_bid.estimate; end`. With estimates of 100 and 105, `bid1 < bid2` returns `true`. The important choice is what ordering means for the class; not every kind of object has a useful greater-than relationship. section 7.6.2

Keep sorting and direct comparison distinct:

  • Defining `<=>` lets instances be sorted in an array or other enumerable without including `Comparable`. section 10.8.3
  • Including `Comparable` as well supplies direct comparisons. A price-ordered `Painting` can then use `>`, `<`, and `between?`; `clamp` can bound it between two prices. section 10.8.3

The comparison rule need not be a price. Strings include `Comparable` and order themselves by character value, so `"a" > "A"` is true. A rock-paper-scissors class instead defines `<=>` around winning moves and uses `>` to choose a winner. In either case, `==` concerns equality under comparison; `equal?` asks whether two references identify the same object. section 8.1.4 section 14.5.5

How The Well-Grounded Rubyist, Fourth Edition covers it

How deep it goes
Works through the three-way `<=>` result and module inclusion, then distinguishes direct comparison from sorting without detailing module internals.
Examples
Uses price-based bids and paintings, character-ordered strings, and a rock-paper-scissors winner calculation.
What it assumes
Assumes familiarity with Ruby classes, instance methods, and `include`; teaches how `<=>` supplies the comparison rule.
What you can do after
Build it from scratch by defining `<=>` and including `Comparable` to give a class direct comparison methods.
How it connects
Connects module mixins and operator methods to equality, sorting, `Enumerable`, and string ordering.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Rubyist, Fourth Edition. The section links point to the parts of the book it draws on.