はじめに
Rubyでバージョン番号を比較したいと考えた時に、そのままの比較では正しく動作しません。たとえば、以下のケースです。
# 文字列同士の比較は辞書順
'3.10' >= '3.2'
# => false
# 文字列と数値の比較
'2.3.0' >= 2.2
# ArgumentError: comparison of String with 2.2 failed
# Rubyのバージョン比較
'2.8.0-dev' > '2.8.0'
# => true
バージョン番号についてはGem::Versionを用いることで、上記のケースを考慮しなくてもよくなります。それを利用して、下記のようにバージョン番号の比較が行えます。
Gem::Version.create('3.10') >= Gem::Version.create('3.2')
# => true
Gem::Version.create('2.3.0') == Gem::Version.create(2.2)
# => false
Gem::Version.create('2.8.0-dev') > Gem::Version.create('2.8.0')
# => false
しかし、逐一Gem::Version.create
を利用して比較するのは大変なのでメソッドにしてみました。
作ったもの
ALLOWED_OPERATORS = %w(> >= == < <=)
def compare?(target_version, operator, comparison_version)
raise "invalid operator: #{operator}" unless validate_operator(operator)
version(target_version).send(operator, version(comparison_version))
end
def validate_operator(operator)
operator.is_a?(String) && ALLOWED_OPERATORS.include?(operator)
end
def version(number)
Gem::Version.create(number)
end
使い方
compare?('3.10', '>=', '3.2')
# => true
compare?('2.3.0', '==', '2.2')
# => false
compare?('2.8.0-dev', '>', '2.8.0')
# => false
並び順も意識しているので見た目としても分かりやすいと思います。
参考
Rubyでバージョン番号を比較するするときはGem::Versionでできる - コード日進月歩
omichelsen/compare-versions: Compare semver version strings to find which is greater, equal or lesser.