Unified method_exists method for ruby
There are loads of different ways to check whether an object (class or instance) contains a given method.
In fact, there are so many different ways that I spent some time working out what was what.
I started out testing each of the relevant Module methods on both a class and instance. This was followed up by testing each of the relevant Object methods on both a class and instance. The full test suite is here.
I summarised the results into a more compact test suite here.
I think I’m correct in stating that there’s no one way to check for the existence of a method (be it public, protected or private) on a class. However, the test results make it slightly easier to scan and create such a method – three variants none-the-less.
The same statement goes for uniformly determining the existence of a method on an instance. Once again the tests helped derive the three implementations here.
Combining these two imlpementations provides us with a uniform method to determine whether the receiver contains a method represented by method_sym.
class Object
def method_exists?(method_sym)
methods = public_methods + protected_methods + private_methods
methods.include?(method_sym.to_s)
end
end
class Class
def method_exists?(method_sym)
methods = public_instance_methods + protected_instance_methods + private_instance_methods
methods.include?(method_sym.to_s)
end
end
class Foo
def foo; end; public :foo
def bar; end; protected :bar
def baz; end; private :baz
end
require 'test/unit'
Class.new(Test::Unit::TestCase) do
def assert_not(expr)
assert ! expr
end
def assert_method_exists_is_working(receiver)
[:foo, :bar, :baz].each do |sym|
assert receiver.method_exists?(sym)
assert receiver.method_exists?(sym.to_s)
end
assert_not receiver.method_exists?(:made_up_method)
assert_not receiver.method_exists?('made_up_method')
end
def test_class
assert_method_exists_is_working(Foo)
end
def test_instance
assert_method_exists_is_working(Foo.new)
end
end
What’s the point you ask? I genuinely have no idea. I’m sure there was one when I started but then my compulsiveness took over and I had to finish for no other reason than to finish.