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

# 課題

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

例えば、 `1.3.2` は `1.2.3` より大きい（一般的には新しい）、`1.3.2` は `2.3.2` より小さい（一般的には古い）というな判定をしたい。

# ふわっとした仕様

バージョニングルールはソフトウェアによって色んなパターンがあるようです。ここでは[バージョンにあれこれ考えを巡らせてみる \- Qiita](https://qiita.com/t_nakayama0714/items/c312bc5edcce6c214856) の「[数字によるバージョン](https://qiita.com/t_nakayama0714/items/c312bc5edcce6c214856#%E6%95%B0%E5%AD%97%E3%81%AB%E3%82%88%E3%82%8B%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3)」を参考に次の内容で対応することにします。

- 同じアプリケーションの２つのバージョン番号同士について「以上」「以下」「より大きい」「より小さい」を判定できる
- バージョン番号は `.` で区切られた文字列
  - 数字以外の文字列は無視する
- メジャー・マイナーの2階層、加えてビルドとリビジョンの4階層だけでなく、複数階層パターンに対応する
- 比較対象のバージョニングルールは階層の数を除いて途中で変更されないこと

## バージョン番号の例

- `1`
- `0.3`
- `0.0.1`
- `My Software 0.0.1`

# シュッと実装

比較メソッドを実装する際に、Ruby の [`Comaprable`](https://docs.ruby-lang.org/ja/latest/class/Comparable.html) モジュールを使います。

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

```ruby
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
```