Demystifying the Gem Version Comparison

Comparing Gem Versions in Ruby


I read the How to compare gem versions in Ruby. Anderson Dias shows us how we can compare using < and > operators. How is this implemented in Ruby gems? I know that comparison is made possible by implementing the <=> method. But where is it in the source code? If you git clone https://github.com/rubygems/gems.git you cannot see the implementation for <=>. So let's find out where it is defined.

 irb
> v = Gem::Version.new('2.1.2')
> v.respond_to?(:<=>)
 => true 
> v.method(:<=>).source_location
 => ["/Users/bparanj/.rvm/rubies/ruby-2.2.3/lib/ruby/2.2.0/rubygems/version.rb", 330] 

Ruby Gems Implementation of <=> Method


Open the version.rb in your editor and look at line 330:

  ##
  # Compares this version with +other+ returning -1, 0, or 1 if the
  # other version is larger, the same, or smaller than this
  # one. Attempts to compare to something that's not a
  # <tt>Gem::Version</tt> return +nil+.

  def <=> other
    return unless Gem::Version === other
    return 0 if @version == other.version

    lhsegments = segments
    rhsegments = other.segments

    lhsize = lhsegments.size
    rhsize = rhsegments.size
    limit  = (lhsize > rhsize ? lhsize : rhsize) - 1

    i = 0

    while i <= limit
      lhs, rhs = lhsegments[i] || 0, rhsegments[i] || 0
      i += 1

      next      if lhs == rhs
      return -1 if String  === lhs && Numeric === rhs
      return  1 if Numeric === lhs && String  === rhs

      return lhs <=> rhs
    end

    return 0
  end

You can see that ruby gems that ships as part of Ruby has the implementation for the <=> method. This is another example of the comparable basic concepts we saw in Ruby Comparable Basics.

Sorting Gem Versions


This allows us to even sort an array of gem versions.

$irb
 > v1 = Gem::Version.new('1.0')
 => #<Gem::Version "1.0"> 
 > v2 = Gem::Version.new('2.0')
 => #<Gem::Version "2.0"> 
 > v15 = Gem::Version.new('1.5')
 => #<Gem::Version "1.5"> 
 > list = [v15, v1, v2]
 => [#<Gem::Version "1.5">, #<Gem::Version "1.0">, #<Gem::Version "2.0">] 
 > list.sort
 => [#<Gem::Version "1.0">, #<Gem::Version "1.5">, #<Gem::Version "2.0">] 

Summary


We can find the implementation of any given method by using source_location method. This is faster than using grep, ack or ag. You learned how the gem comparisons is implemented in ruby gems that comes shipped with Ruby.


Related Articles


Ace the Technical Interview

  • Easily find the gaps in your knowledge
  • Get customized lessons based on where you are
  • Take consistent action everyday
  • Builtin accountability to keep you on track
  • You will solve bigger problems over time
  • Get the job of your dreams

Take the 30 Day Coding Skills Challenge

Gain confidence to attend the interview

No spam ever. Unsubscribe anytime.