views:

170

answers:

6

I know in Ruby that I can use respond_to? to check if an object has a certain method.

But, given the class, how can I check if the instance has a certain method?

Ie, something like

Foo.new.respond_to?(:bar)

But I feel like there's gotta be a better way than instantiating a new instance.

What are your suggestions? Thanks.

+3  A: 

EDIT: This answer is better. Apparently Ruby has this built in, and I somehow missed it. My answer left for reference, regardless.

Ruby classes respond to the methods instance_methods and public_instance_methods. In Ruby 1.8, the first lists all instance method names in an array of strings, and the second restricts it to public methods. The second behavior is what you'd most likely want, since respond_to? restricts itself to public methods by default, as well.

Foo.public_instance_methods.include?('bar')

In Ruby 1.9, though, those methods return arrays of symbols.

Foo.public_instance_methods.include?(:bar)

If you're planning on doing this often, you might want to extend Module to include a shortcut method. (It may seem odd to assign this to Module instead of Class, but since that's where the instance_methods methods live, it's best to keep in line with that pattern.)

class Module
  def instance_respond_to?(method_name)
    public_instance_methods.include?(method_name)
  end
end

If you want to support both Ruby 1.8 and Ruby 1.9, that would be a convenient place to add the logic to search for both strings and symbols, as well.

Matchu
`method_defined?` is better :)
banister
@banister - oh, my, and I somehow missed it! xD Threw a +1 behind @Marc's answer, and added a link to make sure it isn't missed :)
Matchu
+1  A: 

klass.instance_methods.include :method_name #or "method_name", depending on ruby version I think

yxhuvud
+1  A: 

Not sure if this is the best way, but you could always do this:

Foo.instance_methods.include? 'bar'
dbyrne
+1  A: 

try Foo.instance_methods.include? :bar

imightbeinatree at Cloudspace
+3  A: 

You can use method_defined? as follows:

String.method_defined? :upcase # => true

Much easier, portable and efficient than the instance_methods.include? everyone else seems to be suggesting.

Keep in mind that you won't know if a class responds dynamically to some calls with method_missing, for example by redefining respond_to?, or since Ruby 1.9.2 by defining respond_to_missing?.

Marc-André Lafortune
+3  A: 

I don't know why everyone is suggesting you should be using instance_methods and include? when method_defined? does the job.

class Test
    def hello; end
end

Test.method_defined? :hello #=> true
banister
simplest answer ftw