Skip to content

Instantly share code, notes, and snippets.

@nakajima
Forked from joshsusser/protocol.rb
Created June 5, 2009 09:31
Show Gist options
  • Select an option

  • Save nakajima/124168 to your computer and use it in GitHub Desktop.

Select an option

Save nakajima/124168 to your computer and use it in GitHub Desktop.
# Not exactly sure what I'm doing here...
class RestKlass
%W[get post put delete].each { |verb|
define_method(verb) { |res| res }
}
def get; :gotten end
end
class SQLKlass
%W[select insert update delete].each { |verb|
define_method(verb) { |res| res }
}
def select; :selected end
end
class HasManyProtocols
# an object representing a duck type that can be used in a case expression
class Protocol
def initialize(*selectors)
@selectors = selectors
end
def ===(object)
@selectors.all? {|selector| object.respond_to?(selector)}
end
end
REST = Protocol.new(:get, :post, :put, :delete)
SQL = Protocol.new(:select, :insert, :update, :delete)
attr_reader :obj
def initialize(obj)
@obj = obj
end
def result(*args)
case obj
when REST then RestKlass.new
when SQL then SQLKlass.new
end
end
end
require 'spec'
TEST_CASE = proc do |klass|
proc do
it "finds restful object" do
klass.new(RestKlass.new).result.get.should == :gotten
end
it "finds sql object" do
klass.new(SQLKlass.new).result.select.should == :selected
end
end
end
# A DSLy approach to the above..
class HasManyOtherwise
def self.handlers
@handlers ||= {}
end
def self.handle(name, *args)
handlers[name] = args
end
handle RestKlass, :get, :post, :put, :delete
handle SQLKlass, :select, :insert, :update, :delete
def initialize(obj)
@obj = obj
end
def result
HasManyOtherwise.handlers.detect { |key,val|
val.all? { |sym| @obj.respond_to?(sym) }
}[0].new
end
end
describe HasManyProtocols, &TEST_CASE[HasManyProtocols]
describe HasManyOtherwise, &TEST_CASE[HasManyOtherwise]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment