Skip to content

Instantly share code, notes, and snippets.

@sneakin
Created March 24, 2009 03:23
Show Gist options
  • Save sneakin/83914 to your computer and use it in GitHub Desktop.
Save sneakin/83914 to your computer and use it in GitHub Desktop.
rubyfu_kind_of.rb – Extends Object.kind_of? and Class to allow `3.kind_of?(String | Fixnum)` type magic or by doing `3.kind_of?(String, Fixnum)`
# rubyfu_kind_of.rb
# Extends Object.kind_of? and Class to allow `3.kind_of?(String | Fixnum)`
# type magic or by doing `3.kind_of?(String, Fixnum)`
#
# Copyright (C) 2009 Nolan Eakins
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
require 'active_support'
class Class
def |(other)
ClassGroup.new | self | other
end
def <<(mod)
self.send(:include, mod)
self
end
end
class ClassGroup
self << Enumerable
attr_accessor :classes
def initialize
@classes = Array.new
end
def |(other)
raise ArgumentError.new("must be a Class") unless
other.kind_of?(Class) || other.kind_of?(ClassGroup)
classes << other
self
end
def each(&block)
classes.each(&block)
end
end
module Kindness
def self.included(base)
base.alias_method_chain(:kind_of?, :class_group) unless
base.respond_to?(:kind_of_without_class_group?)
base.alias_method_chain(:kind_of?, :var_args) unless
base.respond_to?(:kind_of_without_var_args?)
end
def kind_of_with_class_group?(klass_group)
return kind_of_without_class_group?(klass_group) unless
klass_group.kind_of_without_class_group?(ClassGroup)
klass_group.any? { |k| kind_of_without_class_group?(k) }
end
def kind_of_with_var_args?(*klasses)
return kind_of_without_var_args?(*klasses) if
klasses.length == 1
klasses.any? { |k| self.kind_of_without_var_args?(k) }
end
end
class Object
include Kindness
end
if __FILE__ == $0 || %W(rcov spec).include?(File.basename($0))
require 'spec'
describe __FILE__ do
it "won't futz on reload" do
lambda {
$0 = 'rcov1'
load __FILE__
}.should_not raise_error
end
end
describe Object do
describe '#kind_of?' do
it "can take multiple classes: kind_of?(String | Fixnum)" do
"hello".should be_kind_of(String | Fixnum)
3.should be_kind_of(String | Fixnum)
[ Object.new, proc { }, "hello", 3 ].each do |obj|
obj.should be_kind_of(Object | String | (Proc | Fixnum))
end
end
it "can take multiple classes: kind_of?(String, Fixnum)" do
"hello".should be_kind_of(String, Fixnum)
3.should be_kind_of(String, Fixnum)
[ Object.new, proc { }, "hello", 3 ].each do |obj|
obj.should be_kind_of(Object, String, Proc, Fixnum)
end
end
end
end
describe Class do
before(:each) do
@cg = (String | Fixnum | Proc)
end
it "includes a String & Fixnum" do
[ String, Fixnum, Proc ].each { |k| @cg.classes.should include(k) }
end
it "is a ClassGroup" do
@cg.should be_kind_of(ClassGroup)
end
[ "Hello", 3, proc { } ].each do |obj|
it "knows a #{obj.class}" do
obj.should be_kind_of(@cg)
end
end
[ 3.14, $stderr ].each do |obj|
it "fails on #{obj.class}" do
obj.should_not be_kind_of(@cg)
end
end
end
describe ClassGroup do
before(:each) do
@cg = ClassGroup.new | String | Fixnum
end
it "builds a list of classes" do
@cg.classes.should include(String)
@cg.classes.should include(Fixnum)
end
it "does not like instances" do
lambda { @cg | "Hello" }.should raise_error(ArgumentError)
lambda { @cg | 3.3 }.should raise_error(ArgumentError)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment