Enumerable and Comparable
Fast recall
Quick revision
Core answer
Enumerable and Comparable are Ruby mixins that derive many operations from one core protocol. A collection includes Enumerable and implements each, gaining methods such as map, select, and reduce. An ordered value includes Comparable and implements <=>, gaining <, <=, ==, >=, >, between?, and clamp. <=> should return a negative number, zero, a positive number, or nil when the values cannot be compared.Whether you know Enumerable needs `each` defined and Comparable needs `<=>` defined, and each gives many methods free.
Including Enumerable without defining `each` (raises/returns nil), or Comparable without `<=>`.
Enumerable needs `each` (gives map/select/reduce/sort). Comparable needs `<=>` (gives </>/==/between?/sort). Mixins = define one, get many free.
Interview-ready guide
Interview answer
Enumerable and Comparable are Ruby mixins that build many useful methods from one method supplied by the class. A collection includes Enumerable and defines each. An ordered value includes Comparable and defines <=>. The class keeps control of its own data; the mixin supplies the common operations.
each defines which values the collection exposes and in what order. Once ScoreBoard#each yields every score, select can keep the scores that match a block even though the class never defines select itself. Returning an Enumerator when no block is given also keeps the class compatible with normal Ruby iteration.
<=> is called the spaceship operator. It returns a negative number when the receiver comes first, zero when both values have the same position, a positive number when the receiver comes later, and nil when the values cannot be compared. For a version object, the key line can be [major, minor] <=> [other.major, other.minor].
These mixins are only as correct as the method behind them. each must yield the intended elements consistently, and <=> must give a stable ordering for compatible values. Collection methods such as sort perform the sorting work; Comparable only tells them how two elements compare.
Enumerable and Comparable
Direct Answer
Enumerable and Comparable are Ruby mixins that derive many operations from one core protocol. A collection includes Enumerable and implements each, gaining methods such as map, select, and reduce. An ordered value includes Comparable and implements <=>, gaining <, <=, ==, >=, >, between?, and clamp. <=> should return a negative number, zero, a positive number, or nil when the values cannot be compared.
Deep Dive & Architecture
Enumerable works through inversion of control: the collection decides how elements are exposed, and the mixin supplies algorithms that consume that stream. A tree could yield depth-first, a page set could fetch batches, and a wrapper could filter hidden records. Every inherited operation follows the order and completeness of each.
That makes each a behavioural contract. It should yield every intended element exactly once unless the collection explicitly documents another rule. Returning an Enumerator when no block is supplied lets callers defer the traversal or chain it with other enumerator operations.
Comparable turns a three-way comparison into boolean relationships. The sign of <=> matters, not a requirement to return exactly minus one or one. Returning nil for an unrelated type says there is no sensible ordering; pretending unrelated values are equal can violate symmetry and produce unstable results.
Sorting crosses both protocols. An Enumerable or Array method controls traversal and ordering work, while each element's <=> defines how two values compare. If <=> is inconsistent—for example, a < b and b < a can both become true—higher-level operations cannot produce reliable answers.
Code Example
class ScoreBoard
include Enumerable
def initialize(scores)
@scores = scores
end
def each
return enum_for(:each) unless block_given?
@scores.each { |score| yield score }
end
end
ScoreBoard.new([82, 61, 90]).select { |score| score >= 70 }
# => [82, 90]
class Version
include Comparable
attr_reader :major, :minor
def initialize(major, minor)
@major = major
@minor = minor
end
def <=>(other)
return nil unless other.is_a?(Version)
[major, minor] <=> [other.major, other.minor]
end
end
Version.new(2, 1) > Version.new(1, 9) # => true
Common Mistakes & Pitfalls
Including Enumerable without defining each (raises/returns nil), or Comparable without <=>.
Check your understanding
Answer these without looking back at the article.
- Why does an Enumerable class need to implement `each`?
- What should `<=>` return for an incompatible value?
- Does Comparable itself define `sort`, and how do sortable collections use it?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.