Edited at

2つのバージョン番号文字列について「以上」「以下」「より大きい」「より小さい」「同じ」の比較判定をする

More than 1 year has passed since last update.


課題

アプリケーションのバージョン番号について、以上(「以下」「より大きい」「より小さい」「同じ」)を判定したい。

例えば、 1.3.21.2.3 より大きい(一般的には新しい)、1.3.22.3.2 より小さい(一般的には古い)というな判定をしたい。


ふわっとした仕様

バージョニングルールはソフトウェアによって色んなパターンがあるようです。ここではバージョンにあれこれ考えを巡らせてみる - Qiita の「数字によるバージョン」を参考に次の内容で対応することにします。


  • 同じアプリケーションの2つのバージョン番号同士について「以上」「以下」「より大きい」「より小さい」を判定できる

  • バージョン番号は . で区切られた文字列


    • 数字以外の文字列は無視する



  • メジャー・マイナーの2階層、加えてビルドとリビジョンの4階層だけでなく、複数階層パターンに対応する

  • 比較対象のバージョニングルールは階層の数を除いて途中で変更されないこと


バージョン番号の例


  • 1

  • 0.3

  • 0.0.1

  • My Software 0.0.1


シュッと実装

比較メソッドを実装する際に、Ruby の Comaprable モジュールを使います。

Comparable モジュールの比較演算子を定義する事で、通常の数値比較のように直感的なインターフェースになります(テストケースを参照)。

require 'test/unit'

class VersionComparator
include Comparable

attr_reader :splited_version

def initialize(version)
@splited_version = version.gsub(/[^\d.]+/, '').split('.').map(&:to_i)
end

def <=>(other)
@splited_version <=> other.splited_version
end
end

class TestVersionComparator < Test::Unit::TestCase
def test_ufo
# test <
assert_equal true, VersionComparator.new('0.0.1') < VersionComparator.new('0.0.2')
assert_equal false, VersionComparator.new('0.0.5') < VersionComparator.new('0.0.2')
assert_equal true, VersionComparator.new('0.0.5') < VersionComparator.new('0.1.2')
assert_equal false, VersionComparator.new('0.0.5') < VersionComparator.new('0.0.5')
assert_equal false, VersionComparator.new('0.5') < VersionComparator.new('0.0.5')
assert_equal true, VersionComparator.new('0.0.5') < VersionComparator.new('0.5')
assert_equal true, VersionComparator.new('My Software 0.0.1') < VersionComparator.new('My Software 0.0.2')

# test <=
assert_equal true, VersionComparator.new('0.0.1') <= VersionComparator.new('0.0.2')
assert_equal false, VersionComparator.new('0.0.5') <= VersionComparator.new('0.0.2')
assert_equal true, VersionComparator.new('0.0.5') <= VersionComparator.new('0.1.2')
assert_equal true, VersionComparator.new('0.0.5') <= VersionComparator.new('0.0.5')
assert_equal false, VersionComparator.new('0.5') <= VersionComparator.new('0.0.5')
assert_equal true, VersionComparator.new('0.0.5') <= VersionComparator.new('0.5')
assert_equal true, VersionComparator.new('My Software 0.0.1') <= VersionComparator.new('My Software 0.0.2')

# test >
assert_equal false, VersionComparator.new('0.0.1') > VersionComparator.new('0.0.2')
assert_equal true, VersionComparator.new('0.0.5') > VersionComparator.new('0.0.2')
assert_equal false, VersionComparator.new('0.0.5') > VersionComparator.new('0.1.2')
assert_equal false, VersionComparator.new('0.0.5') > VersionComparator.new('0.0.5')
assert_equal true, VersionComparator.new('0.5') > VersionComparator.new('0.0.5')
assert_equal false, VersionComparator.new('0.0.5') > VersionComparator.new('0.5')
assert_equal false, VersionComparator.new('My Software 0.0.1') > VersionComparator.new('My Software 0.0.2')

# test >=
assert_equal false, VersionComparator.new('0.0.1') >= VersionComparator.new('0.0.2')
assert_equal true, VersionComparator.new('0.0.5') >= VersionComparator.new('0.0.2')
assert_equal false, VersionComparator.new('0.0.5') >= VersionComparator.new('0.1.2')
assert_equal true, VersionComparator.new('0.0.5') >= VersionComparator.new('0.0.5')
assert_equal true, VersionComparator.new('0.5') >= VersionComparator.new('0.0.5')
assert_equal false, VersionComparator.new('0.0.5') >= VersionComparator.new('0.5')
assert_equal false, VersionComparator.new('My Software 0.0.1') >= VersionComparator.new('My Software 0.0.2')

# test ==
assert_equal true, VersionComparator.new('0.0.1') == VersionComparator.new('0.0.1')
assert_equal true, VersionComparator.new('My Software 0.0.2') == VersionComparator.new('My Software 0.0.2')
end
end