lib/option_initializer.rb in option_initializer-1.5.0 vs lib/option_initializer.rb in option_initializer-1.5.1
- old
+ new
@@ -1,59 +1,96 @@
require 'option_initializer/version'
require 'set'
-module OptionInitializer
- class OptionInitializingTemplate
- attr_reader :options
- alias to_h options
-
- def initialize base, options, need_validation
- validate options if need_validation
- @base = base
- @options = options
+unless Class.respond_to?(:|)
+ class Class
+ def | other_class
+ unless other_class.is_a?(Class)
+ raise TypeError, "wrong argument type (expected: Class)"
+ end
+ OptionInitializer::ClassMatch.new(self, other_class)
end
+ end
+else
+ Kernel.warn "Class already has `|' method. OptionInitializer will not override its behavior."
+end
- def new *args, &block
- args = args.dup
- opts = @options
+# @private
+class OptionInitializingTemplate
+ attr_reader :options
+ alias to_h options
- # Convention. Deal with it.
- if args.last.is_a?(Hash)
- validate args.last
- opts = opts.merge(args.last)
- args.pop
- else
- opts = opts.dup
- end
+ def initialize base, options, need_validation
+ validate options if need_validation
+ @base = base
+ @options = options
+ end
- opts.instance_eval do
- def option_validated?
- true
- end
+ def new *args, &block
+ args = args.dup
+ opts = @options
+
+ # Convention. Deal with it.
+ if args.last.is_a?(Hash)
+ validate args.last
+ opts = opts.merge(args.last)
+ args.pop
+ else
+ opts = opts.dup
+ end
+
+ opts.instance_eval do
+ def option_validated?
+ true
end
- args << opts
+ end
+ args << opts
- @base.new(*args, &block)
+ @base.new(*args, &block)
+ end
+
+ def merge opts
+ validate opts
+ self.class.new @base, @options.merge(opts), false
+ end
+
+ def validate hash
+ avals, vals = [:ARG_VALIDATORS, :VALIDATORS].map { |s|
+ self.class.const_get(s)
+ }
+ hash.each do |k, v|
+ avals[k] && avals[k].call(v)
+ vals[k] && vals[k].call(v)
+ vals[nil] && vals[nil].call(k, v)
end
+ end
+end
- def merge opts
- validate opts
- self.class.new @base, @options.merge(opts), false
+module OptionInitializer
+ class ClassMatch
+ def initialize *classes
+ @classes = Set[*classes]
end
- def validate hash
- avals, vals = [:ARG_VALIDATORS, :VALIDATORS].map { |s|
- self.class.const_get(s)
- }
- hash.each do |k, v|
- avals[k] && avals[k].call(v)
- vals[k] && vals[k].call(v)
- vals[nil] && vals[nil].call(k, v)
+ def | other_class
+ unless other_class.is_a?(Class)
+ raise TypeError, "wrong argument type (expected: Class)"
end
+ ClassMatch.new(*@classes.union([other_class]))
end
+
+ def match object
+ @classes.any? { |k| object.is_a? k }
+ end
+
+ def to_s
+ a = @classes.map(&:to_s)
+ [a[0...-1].join(', '), a.last].reject(&:empty?).join(', or ')
+ end
end
+ # @private
module MethodCallShortcut
def method_missing sym, *args, &block
# 1.8
if @base.instance_methods.map(&:to_sym).include?(sym)
new.send sym, *args, &block
@@ -77,10 +114,11 @@
vals[nil] && vals[nil].call(k, v)
end
options
end
+ # @private
def self.included base
unless base.constants.map(&:to_sym).include?(:OptionInitializing)
base.const_set :OptionInitializing, oi = OptionInitializingTemplate.dup
oi.class_eval do
const_set :VALIDATORS, {}
@@ -118,13 +156,17 @@
when Range
raise ArgumentError, "invalid number of arguments specified for #{k}" if v.begin < 0
when Set
raise ArgumentError, "empty set of values specified for #{k}" if v.length == 0
when Array
- raise ArgumentError, "invalid option definition: `#{v}'" unless v.all? { |e| e.is_a?(Class) || e.is_a?(Set) }
+ unless v.all? { |e| [Class, Set, ClassMatch].any? { |kl| e.is_a?(kl) } }
+ raise ArgumentError, "invalid option definition: `#{v}'"
+ end
when Class, :*, :&
# noop
+ when ClassMatch
+ # noop
else
raise ArgumentError, "invalid option definition: `#{v}'"
end
[k.to_sym, v]
}
@@ -189,20 +231,30 @@
raise TypeError, "wrong argument type #{e.class} (expected #{c})" unless e.is_a?(c)
when Set
unless c.include?(e)
raise ArgumentError, "invalid option value: `#{e}' (expected one of #{c.to_a.inspect})"
end
+ when ClassMatch
+ unless c.match e
+ raise TypeError, "wrong argument type #{e.class} (expected #{c})"
+ end
end
end
end
}
when Class
vals[sym] = proc { |v|
if !v.is_a?(nargs)
raise TypeError, "wrong argument type #{v.class} (expected #{nargs})"
end
}
+ when ClassMatch
+ vals[sym] = proc { |v|
+ unless nargs.match v
+ raise TypeError, "wrong argument type #{v.class} (expected #{nargs})"
+ end
+ }
end
end
# Class methods
pairs.each do |pair|
@@ -232,10 +284,10 @@
end
elsif b
raise ArgumentError, "block not expected"
else
case nargs
- when 1, Class, Set
+ when 1, Class, Set, ClassMatch
if v.length == 1
merge(sym => v.first)
else
raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
end