views:

63

answers:

1

It may not be so obvious how respond_to? works in ruby. Consider that:


class A

   def public_method
   end

   protected
   def protected_method
   end

   private
   def private_method
   end

end

obj = A.new
obj.respond_to?(:public_method)
# true - that's pretty obvious
obj.respond_to?(:private_method)
# false - as expected
obj.respond_to?(:protected_method)
# true - WTF?

So if 'obj' responds to protected_method we should expect

obj.protected_method

not to raise an exception, shouldn't we?

...but it raises obviously

Documentation points that calling respond_to? with 2nd argument set to true check private method as well

obj.respond_to?(:private_method, true)
# true

And that's far more reasonable

So the question is how to check if object responds to public method only? Is there a solution better than that?

obj.methods.include?(:public_method)
# true
obj.methods.include?(:protected_method)
# false
+1  A: 

It is currently under debate if respond_to? should look for protected methods or not (check this thread if you can read Japanese).

If my understanding of google translate's blurb is correct, it is likely to change. I'll ask to see where things are at.

Note some classes might use #method_missing and specialize #respond_to? (or better, in the upcoming Ruby 1.9.2 specify a #respond_to_missing?), in which case your obj.methods.include? will not be reliable.

Marc-André Lafortune
It's hard for me to understand translated Japanese but anyway good to know that ruby core consider that issue. At least one may use obj.class.public_method_defined?(:protected_method) and it works as expected but won't handle singleton methods, so I rather consider that as workaround not real solution
mlomnicki