-
-
Save ahoward/1446030 to your computer and use it in GitHub Desktop.
class Version < ::String | |
class Error < ::StandardError; end | |
attr :major | |
attr :minor | |
attr :teeny | |
def Version.default | |
Version.for('0.0.0') | |
end | |
def Version.for(*args) | |
version = args.size == 1 && args.first | |
case version | |
when Version | |
version | |
else | |
Version.new(*args) | |
end | |
end | |
def Version.numbers(version) | |
Version.for(version).numbers | |
end | |
def initialize(*args, &block) | |
super(args.flatten.join('.')) | |
ensure | |
@major, @minor, @teeny = strip.split(/\./).map{|v| v.to_i} | |
end | |
def <=> other | |
numbers <=> Version.for(other).numbers | |
end | |
def numbers | |
[major, minor, teeny] | |
end | |
%w( major minor teeny ).each do |number| | |
module_eval <<-__, __FILE__, __LINE__ | |
def bump_#{ number }! | |
@#{ number } += 1 | |
replace(numbers.join('.')) | |
self | |
end | |
def bump_#{ number } | |
dup.bump_#{ number }! | |
end | |
__ | |
end | |
alias_method('bump', 'bump_minor') | |
alias_method('bump!', 'bump_minor!') | |
end |
SomeClass.for, in my code, nearly always conforms to the following interface:
"given a bucket of random arguments, do your best to make a choice at how to call 'new' with them. as a special case, iff the object is already of the class in question, simply return it"
it's a sort of cast-or-build factory that let's me do things like #L34 without needing to worry about making lots of extraneous objects. a more sophisticated example: https://github.com/ahoward/map/blob/master/lib/map.rb#L42 - note that this one even works for class Foo < ::Map...
some other examples:
I'm totally in for that - but I've reverted to the Gem::Version class since in 99 percent of the cases it's there for me anyway. Like here https://github.com/julik/update_hints/blob/master/lib/update_hints.rb#L28
using Gem::Version is a good idea. in my case i really needed domain specific '@version.bump!'
so good. can you explain the Version::for method a little?