From: Massimiliano Mirra Date: 2002-10-23T18:13:45+09:00 Subject: Re: Sort::Versions (was Re: Perl multiple match RE in Ruby?) On Tue, Oct 22, 2002 at 09:03:14PM +0900, Nikodemus Siivola wrote: > > That would save the step of extending those classes in code. > > How about adding that to the Version module inside a BuiltinExt module, so > that to extend the classes you would just: I'll throw mine in too; I wrote it for rpkg. This makes Version a Comparable object. (Have a look at the tests for usage examples.) class Version include Comparable def Version.[](*args) new(*args) end def initialize(s, separators = '.-') separators = separators.split('') items_regex_src = separators.collect {|sep| Regexp.escape(sep)}.join("|") seps_regex_src = separators.collect {|sep| Regexp.escape(sep)}.join items_regex = Regexp.compile(items_regex_src) seps_regex = /[^#{seps_regex_src}]/ @v = s.split(items_regex).collect {|n| Integer(n) rescue n} @sep = s.gsub(seps_regex, '').split('') end def to_a @v end def to_s s = '' @sep.each_with_index do |sep, i| s << "#{@v[i]}#{sep}" end s << "#{@v.last}" return s end def inspect @v.inspect end def [](n) @v[n] end def <=>(other) raise unless other.is_a? Version comp = 0 @v.each_with_index do |n, i| if n and other[i] comp = n <=> other[i] elsif n.nil? comp = -1 elsif other[i].nil? comp = +1 else raise "This should never happen!" end if comp == 0 next else break end end return comp end end if $0 == __FILE__ require 'test/unit' class Version def separators @sep end end class TestVersion < Test::Unit::TestCase def test_version_to_array v = Version['0.1.0'] assert [0, 1, 0], v.to_a end def test_can_access_revision_number v = Version['0.1.0'] assert_equal 0, v[0] assert_equal 1, v[1] assert_equal 0, v[2] end def test_non_dot_separators v = Version['0.1.0-20021099'] assert_equal 0, v[2] assert_equal 20021099, v[3] end def test_can_mix_numbers_and_strings v = Version['0.1.4-unstable'] assert_equal 0, v[0] assert_equal 1, v[1] assert_equal 4, v[2] assert_equal 'unstable', v[3] end def test_can_compare_equal_versions v1 = Version['0.1.0'] v2 = Version['0.1.0'] assert_equal v1 <=> v2, 0 assert v1 == v2 assert_equal v1, v2 end def test_can_compare_different_versions v1 = Version['0.1.0'] v2 = Version['0.1.2'] assert_equal v1 <=> v2, -1 assert_equal v2 <=> v1, 1 assert v1 < v2 assert v2 > v1 end def test_can_compare_different_versions_with_different_number_of_items v1 = Version['0.1.0'] v2 = Version['0.1.0.2'] assert v2 > v1 v1 = Version['0.1.0'] v2 = Version['0.1.0-20021010'] assert v2 > v1 v1 = Version['0.1.0'] v2 = Version['0.1.0-unstable'] assert v2 > v1 end def test_can_reconstruct_version_string s = '0.1.0-unstable-20021010' v = Version[s] assert_equal s, v.to_s end def test_finds_separators s = '0.1.0-unstable-20021010' v = Version[s] assert_equal ['.', '.', '-', '-'], v.separators end def test_unique_version_item_accepted v = Version['0123_done'] assert_equal ["0123_done"], v.to_a end def test_allow_alphabetic_only_versions v = Version['cvs'] assert_equal ["cvs"], v.to_a end end end