Sandip Mane
by Sandip Mane
2 min read

Categories

  • Ruby

Tags

  • module
  • ruby

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:

And as always, thanks for reading!😃