Dan Zawadzki Dan Zawadzki - 1 month ago 9
Ruby Question

Method, which return list of instance methods

I'm stuck with two things. This is structure of my file.

class Person
#...
def self.class_name (object)
object.class.name
end
end

class Worker < Person
#...
end

class Client < Person
#...
end

c = Client.new("1", "2", "3", "4")
Person.class_name(c)


I would like to create method, where as argument i can put some object and it will detect, what class is it and return me list of all instance methods, which don't require any argument. Later i need to somehow use all these methods.

I have found this:

testObject.class.name
# returns name of class as a string

Class.instance_methods(false)
# returns list of instance method, which were defined in Class


First problem, is that i don't understand why i can't make something like

className = testObject.class.name
className.instance_methods(false)


I suppose, that's because i got just class name, as a sting, not a real reference to the class. I have even created simple class_name method, which returns correct name of class, but i'm wondering how i can use
instance_methods(false)
, once i have this name. Also is there some option to choose only methods, which don't require any argument?

Answer

I would like to create method, where as argument i can put some object and it will detect, what class is it and return me list of all instance methods

class Person
  def self.instance_methods(object)
    object.class.instance_methods(false)
  end
end

Usage:

c = Client.new("1", "2", "3", "4")
Person.instance_methods(c)
#=> returns an array of all instance methods defined in Client class

Also is there some option to choose only methods, which don't require any argument?

Yes, you have to check method's arity and select those, which has zero:

class Person
  def self.instance_methods_with_arity_zero(object)
    object.class.instance_methods(false).map do |method|
      object.method(method).arity.zero?
    end
  end
end

Usage:

c = Client.new("1", "2", "3", "4")
Person.instance_methods_with_arity_zero(c)
#=> returns an array of instance methods which take no arguments defined in Client class

The latter method can be shortened to use the first defined method:

def self.instance_methods_with_arity_zero(object)
  # we are using the previously defined instance_methods method
  instance_methods(object).map { |method| object.method(method).arity.zero? }
end