Ruby’s
Comparable
module is used when implementing class objects needs to be ordered or compared.
It is also used by ruby’s Enumerable
module for ordering the collection.
Read the blog about
enumerable module.
<=>
The class must define the <=>
operator,
which compares the receiver against another object,
returning a value less than 0
, 0
or greater than 0
.
When the other object is not comparable, it should return nil
.
Comparable uses this to implement the conventional comparison operators (<
, <=
, ==
, >=
, and >
) and the method #between?
.
class Grade
def initialize(name, marks)
@name = name
@marks = marks
end
def to_s
"#{name}: #{marks}"
end
end
> ethan = Grade.new("Ethan", 80)
> jason = Grade.new("Jason", 80)
> ethan == jason # => false
We want to be able to compare the objects with marks
of each object.
Here it doesn’t seem to be the case.
We can do that by including Comparable
module and
implementing <=>
operator in our class.
class Grade
include Comparable
...
def <=>(other)
if other.is_a? Grade
marks <=> other.marks
elsif other.is_a? Numeric
marks <=> other
end
end
end
> ethan = Grade.new("Ethan", 80)
> jason = Grade.new("Jason", 80)
> ethan == jason # => true
It works!😎 Let’s try a few more.
> ethan = Grade.new("Ethan", 75)
> karen = Grade.new("Karen", 50)
> corey = Grade.new("Corey", 80)
> jason = Grade.new("Jason", 60)
> ethan < jason # => false
> corey > jason # => true
> ethan.between?(jason, corey) # => true
> [ethan, jason].include? 75 # => true
> [ethan, jason].include? jason # => true
> puts [ethan, karen, corey, jason].sort
Karen: 50
Jason: 60
Ethan: 75
Corey: 80
Lets try to use methods from Enumerable module
> [ethan, karen, corey, jason].minmax
Karen: 50
Corey: 80
> [ethan, karen, corey, jason].sum
# => TypeError (Grade can't be coerced into Integer)
We need to implement coerce
method to
perform arithmatic operations with our class objects.
coerce
Coercion mechanism is used by Ruby to handle mixed-type numeric operations: it is intended to find a compatible common type between the two operands of the operator.
Add this method to our class
def coerce(v)
[v, marks]
end
Now we should we able to perform sum
> [ethan, karen, corey, jason].sum
=> 265
Finally,
In this post, we saw how we can add Comparable
module to
our classes with just include
and <=>
method.
We also saw how we can coerce
these objects to use with numeric operations.
Here’s final code for our class: