Skip to content

Instantly share code, notes, and snippets.

@pda
Created January 9, 2012 06:46
Show Gist options
  • Save pda/1581535 to your computer and use it in GitHub Desktop.
Save pda/1581535 to your computer and use it in GitHub Desktop.
MethodHuntingDelegator
class Book < SomeModelThing
attr_reader :title, :blurb
end
class Course < SomeModelThing
attr_reader :name, :description
end
class SearchResult < MethodHuntingDelegator
def description
hunt_and_call :description, :blurb
end
def title
hunt_and_call :title, :name
end
end
# simulate the results of a search with mixed result types
results = [ Book.first, Course.first ].map(&SearchResult.method(:new))
results.each { |r| puts "#{r.title}: #{r.description}" }
require "delegate"
class MethodHuntingDelegator < SimpleDelegator
def hunt_and_call *candidates
hunt_method(*candidates).call
end
private
def hunt_method *candidates
__getobj__.method candidates.detect(
->{ raise Error.new(candidates, __getobj__) },
&__getobj__.method(:respond_to?)
)
end
class Error < StandardError
def initialize candidates, object
super "#{candidates.inspect} not implemented by #{object.inspect}"
end
end
end
require "spec_helper"
require "method_hunting_delegator"
describe MethodHuntingDelegator do
context "decorating a string" do
let(:delegate) { "abcd" }
let(:delegator) { MethodHuntingDelegator.new(delegate) }
describe "#hunt_and_call" do
it "delegates [ :not_a_method, :length, :upcase ] to String#length" do
delegator.hunt_and_call(:not_a_method, :length, :upcase).should == 4
end
it "raises MethodHuntingDelegator::Error for [ :nope_A, :nope_B ]" do
expect do
delegator.hunt_and_call(:nope_A, :nope_B)
end.to raise_error(MethodHuntingDelegator::Error)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment