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:
