A recent bug hunt led me to discover the issue was caused by some well-meaning attempts at backward compatibility, but a not-so-great choice of how to evaluate the version of Ruby in use
unless RUBY_VERSION =~ /^1\.9/
# supply a method not available before Ruby 1.9.x via monkey-patch
end
So as Ruby 2.x became prevalent, the above code failed the check and supplied a method that was actually incompatible with Ruby versions >= 1.9.x.
I’ve also seen versions treated as decimal numbers and then compared, e.g.
this_version = Float('1.9')
other_version = Float(other_version_string)
if this_version > other_version
# ...
end
That seems like it should work but it has two failings.
If we think of the first number as the “major version” number, and the second as the “minor version” number, what’s the next minor version after 1.9
?
Normally it would be 1.10
. So how would that go in our numerical comparision?
if Float('1.9') > Float('1.10')
# ...
end
Decimal 1.10
is actually 1.1
(dropping the insignificant 0), and is therefore less than 1.9
.
The other problem is if you wanted to have semantic versioning with three version indicator values- “major version”, “minor version”, and “patch version”. E.g. 1.9.3
. We can’t use a decimal here.
The solution is not to treat a version number as anything like a decimal. It is three distinct whole number values, grouped together, needing a comparison at each level.
If you are using Ruby, you can use the Gem::Version library, it does the right thing.