Aman King

A Ruby object's...Aman King's BlikiControl PanelChange LogBrowse PagesSearch?

A Ruby object's own methods

Often times, when I'd like to check what all an object can do, I'd fire the following in irb:

obj = DateTime.new # or whatever
obj.methods.sort
or better yet, if I have some idea about what I'm looking for, say a method with the word "sec", I'd type:
obj.methods.grep /sec/

The reason I have to do the above is that I want to avoid listing all the methods that the object can respond to, including ==, <==>, etc.

A quick way that I've come up with to list just the methods defined for that object, ignoring inherited ones ('noise'), is:

class Object
 def own_methods
   (methods - (self.class.ancestors - [self.class]).collect { |k| k.instance_methods }.flatten).sort
 end
end

Now, to look up an object's own methods was as simple as:

obj.own_methods

Next I decided to make this a bit more flexible such that you can specify the number of levels of ancestors you want to include in the listing. Also, it should work for getting class methods for a class and not just instance methods. And so finally after some test-driving, this is what I came upon:

class Object
 def own_methods(levels_up = 0)
   tree, methods_to_exclude = self.kind_of?(Class) ? [self.ancestors, :methods] : [self.class.ancestors, :instance_methods]
   inherited_methods = tree[levels_up + 1, tree.size].collect { |k| k.send(methods_to_exclude) }.flatten
   methods - inherited_methods
 end
end
 
if __FILE__ == $0
  require 'test/unit'
  class OwnMethodsTest < Test::Unit::TestCase
    def setup
      grandparent_class = Class.new do
        def instance_method_from_grandparent; end
        def self.class_method_from_grandparent; end
      end      
      parent_class = Class.new(grandparent_class) do
        def instance_method_from_parent; end
        def self.class_method_from_parent; end
      end
      @klass = Class.new(parent_class) do
        def an_instance_method; end
        def self.a_class_method; end
      end
    end
 
    def test_own_instance_methods
      assert_equal ["an_instance_method"], @klass.new.own_methods
      assert_equal ["an_instance_method", "instance_method_from_parent"].sort, @klass.new.own_methods(1).sort
      assert_equal ["an_instance_method", "instance_method_from_parent", "instance_method_from_grandparent"].sort, @klass.new.own_methods(2).sort
    end
 
    def test_own_class_methods
      assert_equal ["a_class_method"], @klass.own_methods
      assert_equal ["a_class_method", "class_method_from_parent"].sort, @klass.own_methods(1).sort
      assert_equal ["a_class_method", "class_method_from_parent", "class_method_from_grandparent"].sort, @klass.own_methods(2).sort
    end
  end
end

Here is how this is now helpful to me in irb:

require 'ownmethods'
require 'date'
 
DateTime.ancestors # => [DateTime, Date, Comparable, Object, Kernel]
DateTime.own_methods.sort # => ["now"]
DateTime.new.own_methods.sort # => ["hour", "min", "new_offset", "newof", "of", "offset", "sec", "sec_fraction", "zone"]
DateTime.new.own_methods(1).sort # => ["+", "-", "<<", "<=>", ">>", "_dump", "ajd", "amjd", "asctime", "ctime", "cwday",..., "yday", "year", "zone"]

Tags: technology:coding, technology:ruby Last modified 03:25 Mon, 6 Oct 2008 by AmanKing. Accessed 1,170 times Children What Links Here share Share Except where expressly noted, this work is licensed under a Creative Commons License.