15

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
Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
mlomnicki
  • 167
  • 1
  • 10

2 Answers2

12

From the documentation:

Returns true if obj responds to the given method. Private and protected methods are included in the search only if the optional second parameter evaluates to true

When the question was written (Ruby 1.8.7):

Returns true if obj responds to the given method. Private methods are included in the search only if the optional second parameter evaluates to true.

Ben Aubin
  • 5,542
  • 2
  • 34
  • 54
wanghao
  • 3,335
  • 2
  • 18
  • 13
  • 1
    The question is from 2010. Back then in Ruby 1.8.7 the docs stated that: "Returns true> if obj responds to the given method. Private methods are included in the search only if the optional second parameter evaluates to true." – steenslag Jun 25 '14 at 15:48
  • 2
    Still a valuable answer. I just discovered this curious bug when upgrading an old project from Ruby `1.8.7` to Ruby `2.1.1`. – Michael Yagudaev Aug 12 '14 at 23:41
  • It is on [ruby-doc.org](http://ruby-doc.org/core-2.2.1/Object.html#method-i-respond_to-3F) now. – Ivan Kolmychek Mar 25 '15 at 12:41
9

It is under debate if respond_to? should look for protected methods or not (check this issue)

Matz has stated that it will probably change in Ruby 2.0.

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

Peter Brown
  • 50,956
  • 18
  • 113
  • 146
Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
  • 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 Apr 03 '10 at 01:24