
Untitled
By: a guest on
May 5th, 2012 | syntax:
None | size: 1.28 KB | hits: 13 | expires: Never
module Kernel
def match_class?( class_spec )
case class_spec
when Class
# A plain value
return false unless self.is_a? class_spec
when Hash
# When we expect a keyed enumerator
return false unless self.method(:each)
# A hashlike each will return two values
self.each do |(k,v)|
key_type = class_spec.keys.select { |s| k.is_a? s }
# Pass if any of the possible spec types fit the data.
return false unless key_type.any? { |s| v.match_class?( class_spec[s] ) }
end
when Array
# When we expect an enumerator
return false unless self.method(:each)
# Treat the array of specs as a repeatable sequence
# Make sure the data matches each spec in turn
spec_list = class_spec.each.cycle
self.each do |i|
next_spec = spec_list.next
return false unless i.match_class?( next_spec )
end
end
true
end
end
# Examples:
# Simple, and overkill. Should have used is_a?
1.match_class? Integer
# Slightly more complex...
[ 1, 2, 3 ].match_class? [ Integer ]
# Much more complex...
[ { :foo => 1 }, { :foo => 2 } ].match_class?( [ { Symbol => Integer } ] )
# And to prove it works, this will fail:
[ { :foo => 1 }, { :foo => 2.0 } ].match_class?( [ { Symbol => Integer } ] )