30 Days of Tech: Day 11 - Method Sorta Missing
June 11th, 2008
Method missing magic can often be a code smell leading you to question your design. Sometimes, however, it can be a boon. For those of us who have trouble spelling or remembering the exact names of methods, we can make method missing help with method lookup. Since we’re good TDDers, we’ll start with some tests specifying the behavior we want …
Method missing magic can often be a code smell leading you to question your design. Sometimes, however, it can be a boon. For those of us who have trouble spelling or remembering the exact names of methods, we can make method missing help with method lookup. Since we’re good TDDers, we’ll start with some tests specifying the behavior we want:
class TestMethodSortaMissing < Test::Unit::TestCase
class TestClass
def do_something; :do_something; end
def nothing_to_do; :nothing_to_do; end
end
def test_do_something_can_be_invoked_exactly
assert_equal :do_something, TestClass.new.do_something
end
def test_do_something_can_be_invoked_fuzzily
assert_equal :do_something, TestClass.new.something_do_to
end
def test_nothing_to_do_can_be_invoked_exactly
assert_equal :nothing_to_do, TestClass.new.nothing_to_do
end
def test_nothing_to_do_can_be_invoked_fuzzily
assert_equal :nothing_to_do, TestClass.new.do_nothing
end
def test_simple_mispellings_can_be_invoked
assert_equal :do_something, TestClass.new.do_somthing
assert_equal :do_something, TestClass.new.do_someting
end
def test_a_dissimilar_message_raises_an_error
assert_raises(NoMethodError) do
TestClass.new.a_dissimilar_method
end
end
end
To make the tests pass, we’ll employ the help of the Amatch gem, which implements a few string matching algorithms.
sudo gem install amatch
And then we’ll override method_missing on Object to run a pattern match against the available methods
class Object
alias_method :__exact_method_missing, :method_missing
def method_missing(sym, *args, &block)
symbol_pattern = Amatch::PairDistance.new(sym.to_s)
methods.each do |m|
return send(m, *args, &block) if symbol_pattern.similar(m, /_/) > 0.75
end
__exact_method_missing(sym, *args, &block)
end
end
Now when an object doesn’t understand the message you’ve sent it it will do it’s best to figure out what you mean. If it can’t figure it out based on string analysis, it will fall back to raising an error as usual. The best part is now I don’t have to improve my spelling!
Sorry, comments are closed for this article.