Compare version numbers with pessimistic constraints http://shorts.jeffkreeftmeijer.com/2014/compare-version-numbers-with-pessimistic-constraints/
class Version | |
include Comparable | |
attr_reader :major, :minor, :patch | |
def initialize(number) | |
@major, @minor, @patch = number.split('.').map(&:to_i) | |
end | |
def to_a | |
[major, minor, patch].compact | |
end | |
def <=>(version) | |
(major.to_i <=> version.major.to_i).nonzero? || | |
(minor.to_i <=> version.minor.to_i).nonzero? || | |
patch.to_i <=> version.patch.to_i | |
end | |
def matches?(operator, number) | |
version = Version.new(number) | |
return self == version if operator == '=' | |
return self > version if operator == '>' | |
return self < version if operator == '<' | |
return version <= self && version.next > self if operator == '~>' | |
end | |
def next | |
next_version = to_a | |
if next_version.length == 1 | |
next_version[0] += 1 | |
else | |
next_version[-2] += 1 | |
next_version[-1] = 0 | |
end | |
Version.new(next_version.join('.')) | |
end | |
end |
require 'minitest/autorun' | |
require_relative 'version' | |
describe Version do | |
before do | |
@version = Version.new('1.2.0') | |
end | |
it "has a major version number" do | |
assert @version.major, 1 | |
end | |
it "has a minor version number" do | |
assert @version.minor, 2 | |
end | |
it "has a patch level version number" do | |
assert @version.patch, 0 | |
end | |
it "is equal" do | |
assert @version == Version.new('1.2.0') | |
end | |
describe "concerning comparisons" do | |
it "compares major version numbers" do | |
assert Version.new('2') > Version.new('1') | |
assert Version.new('1') < Version.new('2') | |
end | |
it "compares minor version numbers" do | |
assert Version.new('1.2') > Version.new('1.1') | |
assert Version.new('1.1') < Version.new('1.2') | |
end | |
it "compares patch level version numbers" do | |
assert Version.new('1.1.2') > Version.new('1.1.1') | |
assert Version.new('1.1.1') < Version.new('1.1.2') | |
end | |
end | |
describe "concerning version matching" do | |
it "matches versions with the '=' operator" do | |
assert Version.new('1.2.0').matches?('=', '1.2.0') | |
assert Version.new('1.2.0').matches?('=', '1.2') | |
assert !Version.new('1.2.0').matches?('=', '1.1') | |
end | |
it "matches versions with the '>' operator" do | |
assert Version.new('1.1').matches?('>', '1.0') | |
assert !Version.new('1.0').matches?('>', '1.0') | |
assert !Version.new('1.0').matches?('>', '1.1') | |
end | |
it "matches versions with the '<' operator" do | |
assert Version.new('1.0').matches?('<', '1.1') | |
assert !Version.new('1.0').matches?('<', '1.0') | |
assert !Version.new('1.1').matches?('<', '1.0') | |
end | |
it "matches versions with the '~>' operator" do | |
assert Version.new('1.0').matches?('~>', '1') | |
assert Version.new('1.0').matches?('~>', '1.0') | |
assert Version.new('1.0').matches?('~>', '1.0.0') | |
assert Version.new('1.1').matches?('~>', '1') | |
assert Version.new('1.1').matches?('~>', '1.0') | |
assert !Version.new('1.1').matches?('~>', '1.0.0') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Do you have a licence for this?