The Comparable Module
Comparable is a Ruby mixin that turns a single <=> method you write into the full set of comparison operators — < , <= , == , > , >= , plus between? and clamp .
Learn The Comparable Module in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll make your own classes orderable and sortable by defining just one method.
What You'll Learn in This Lesson
1️⃣ Define <=> and include Comparable
The spaceship operator <=> answers one question: is the left object less than ( -1 ), equal to ( 0 ), or greater than ( 1 ) the right? Define it, include Comparable , and every comparison operator appears for free. A neat trick is to delegate to an Array of fields, whose own <=> compares element by element.
2️⃣ between? and clamp Come Free
Beyond the operators, Comparable hands you two practical helpers. between?(low, high) checks whether an object falls inside a range, and clamp(low, high) pulls an out-of-range value back to the nearest boundary — perfect for limiting volume, brightness, or a temperature reading.
3️⃣ Sorting Custom Objects
Because Array#sort , min , and max all call <=> , defining it once makes your objects sortable everywhere. Keep <=> in natural ascending order for clarity, then reverse at the call site if you want descending. sort_by is often clearer still when you just want to sort on one attribute.
🎯 Your Turn
The Book class is almost there — it just needs the comparison operator. Replace the ___ with the operator that returns -1 , 0 , or 1 .
Build a Money class that stores cents, includes Comparable, and demonstrates sort, min, max, between?, and clamp. Run with ruby money.rb .
📋 Quick Reference — Comparable
Practice quiz
What must the spaceship operator <=> return?
- true or false
- Always an Integer 0..100
- -1, 0, or 1 (or nil if uncomparable)
- The two objects in an array
Answer: -1, 0, or 1 (or nil if uncomparable). <=> returns -1 (less), 0 (equal), 1 (greater), or nil when the objects can't be compared.
What single method must you define to get all comparison operators from Comparable?
- <=>
- ==
- compare
- <
Answer: <=>. Define <=> and include Comparable; the module derives <, <=, ==, >, >=, between?, and clamp.
If you define <=> but forget to include Comparable, calling obj1 < obj2 will:
- Work fine
- Return nil
- Compare by object id
- Raise NoMethodError because < isn't defined
Answer: Raise NoMethodError because < isn't defined. <=> alone doesn't create <; you must include Comparable to derive the operators.
What does [2, 1] <=> [2, 10] return?
- 1
- -1
- 0
- nil
Answer: -1. Arrays compare element by element: 2 == 2, then 1 < 10, so the result is -1.
Which TWO helper methods does Comparable provide beyond the operators?
- between? and clamp
- map and select
- sort and reverse
- min and max
Answer: between? and clamp. Comparable gives you between?(low, high) and clamp(low, high) for free.
Temp.new(40).clamp(Temp.new(18), Temp.new(30)) returns the temperature:
- 40
- 18
- 30
- nil
Answer: 30. clamp pulls an out-of-range value back to the nearest boundary; 40 clamps down to the high, 30.
Why does Array#sort work on your custom objects once they're Comparable?
- sort reads instance variables directly
- sort calls <=> under the hood to order elements
- sort uses == only
- It doesn't — you must write your own sort
Answer: sort calls <=> under the hood to order elements. sort, min, and max all rely on <=>, so defining it once makes objects sortable everywhere.
The recommended way to sort custom objects in DESCENDING order is to:
- Reverse the logic inside <=>
- Define a separate sort_desc method
- Use min instead of max
- Keep <=> ascending and reverse at the call site (e.g. array.sort.reverse)
Answer: Keep <=> ascending and reverse at the call site (e.g. array.sort.reverse). Keep <=> in natural ascending order and reverse at the call site, so max stays intuitive.
How do Comparable and Enumerable differ?
- They are the same module under two names
- Comparable orders one object vs another (<=>); Enumerable traverses a collection (each)
- Comparable is for arrays only
- Enumerable needs <=>, Comparable needs each
Answer: Comparable orders one object vs another (<=>); Enumerable traverses a collection (each). Comparable orders objects via <=>; Enumerable traverses collections via each.
Why store money as cents (integers) when making it Comparable?
- Cents sort alphabetically
- Comparable rejects floats
- Integers compare cleanly without floating-point drift
- It uses less memory than any other approach
Answer: Integers compare cleanly without floating-point drift. Comparable units like cents compare exactly, avoiding float rounding surprises.