How do I inspect the methods of a Ruby object? - ruby

I am wondering if there is a Ruby method call that shows only the methods defined by the Ruby object it's called from, as opposed to all the methods defined by its ancestor classes, which is what methods seems to do.

methods takes an optional boolean parameter, which specifies whether to also list the methods from the object's class and its superclasses or just the object's singleton methods. So you can do obj.methods(false) to only get the singleton methods defined on obj.
If you want the methods defined by the object's class, but not those defined by its superclasses, you can get that by calling instance_methods(false) on the object's class, so it's obj.class.instance_methods(false).

I'm partial to obj.methods.sort but some of the other answers are better in certain cases as they describe
You can also use obj.methods.sort.grep /foo/ to find method names matching the regexp.
This is helpful when you have an idea of what you're looking for.

You have a few options - object.methods, object.public_methods, object.singleton_methods... it depends on what you want. Since they both return an array, you might want to try something like:
# obj is the current object
parent = obj.class.superclass
methods = (obj.methods - parent.methods)

Related

In the context of ruby modules, what is the difference between a self.method and a regular method?

So, from what I understand, in a class, a self.method is like a class method, whereas a regular method is like an instance method. But, as you can't instantiate a module, why would I use one over the other? What is the difference between these two in a module?
So, from what I understand, in a class, a self.method is like a class method, whereas a regular method is like an instance method.
That is not true. Ruby only has one single kind of method: instance methods. So, what you call a "regular method" is not "like" an instance method, it is an instance method. And there are no class methods in Ruby, every method is an instance method.
There are two ways to define a method in Ruby: with an explicit definee (def foo.bar) and without (def bar, which is then using the default definee).
In the first case, it is easy to know where a method will be defined: if you say def foo.bar, the method will become an instance method of foo's singleton class, always.
If you say def bar, the method becomes an instance method of the default definee, which usually, but not always, is the closest lexically enclosing module definition body. The most notable exception is a method that is defined directly in a script body, in this case, there is no lexically enclosing module definition, and the default definee is Object instead. In fact, there is even another twist: the method will be implicitly defined as private as well.
So, in your case, the first method will become an instance method of the singleton class of self (and inside a module definition body, self is the module itself), the second method will become an instance method of the module.
But, as you can't instantiate a module,
Ruby has a feature called inheritance. While it is true that you can directly instantiate a module, you can instantiate a class that inherits from a module. In fact, since the Object class inherits from the Kernel module (which has instance methods like Kernel#puts or Kernel#require, which may have used once or twice), and almost every class directly or indirectly inherits from Object, it is highly likely that you will have in your Ruby programming already have instantiated an indirect instance of a module and used a module's instance methods.
Enumerable is another important module in Ruby that contains methods like map, select, etc. that both Array and Hash inherit from.
why would I use one over the other?
There's really not much to it: you'd use an instance method, if you want to … well use an instance method, i.e. want to have a method that has privileged access to the internal representation of self across many different instances of the same module.
You would use a method of the singleton class, if you want the method to be only available for that single object.
There is one and only one reason for having module methods: to invoke those methods on the module in which they defined (using self: def self.my_method...). An example of this is Ruby's built-in Math module. All methods in this module are module methods. These methods are all invoked with Math as their explicit receiver (e.g., Math.sqrt(2.5)). In effect, they are used like functions in non-OO languages.
When you include, prepend or extend a module from a class, any module methods are simply ignored.
You might find this (timely) article helpful in understanding the Ruby object model and how methods are “looked up”: https://www.honeybadger.io/blog/ruby-method-lookup/

Ruby - in what module is `each` implemented in? [duplicate]

When sent a message, a Ruby object searches to see whether it has a method by that name to respond with. Its method lookup searches in the following order, and uses the first method it finds.
Singleton methods defined on itself (aka methods on its "eigenclass")
Methods defined in its class
Any modules mixed into its class, in reverse order of inclusion (only the earliest inclusion of a given module has any effect - if the superclass includes module A, and the subclass includes it again, it’s ignored in the subclass; if the subclass includes A then B then A, the second A is ignored) (update: note that this was written before Module.prepend existed)
Its parent class
Any methods mixed into the parent class, the parent's parent, etc.
Or, to put it more simply, it looks on itself, then everything in self.class.ancestors in the order they're listed.
This lookup path is followed at the moment the method is called; if you make an instance of a class, then reopen the class and add a method or mix one in via a module, the existing instance will gain access to that method.
If all of this fails, it looks to see if it has a method_missing method, or if its class does, its parent class, etc.
My question is this: aside from examining the code by hand, or using example methods like puts "I'm on module A!", can you tell where a given method came from? Can you, for example, list an object's methods and see "this one is on the parent class, this one is on module A, this one is on the class and overrides the parent class," etc?
Object#method returns a Method object giving meta-data about a given method. For example:
> [].method(:length).inspect
=> "#<Method: Array#length>"
> [].method(:max).inspect
=> "#<Method: Array(Enumerable)#max>"
In Ruby 1.8.7 and later, you can use Method#owner to determine the class or module that defined the method.
To get a list of all the methods with the name of the class or module where they are defined you could do something like the following:
obj.methods.collect {|m| "#{m} defined by #{obj.method(m).owner}"}
Get the appropriate Method (or UnboundMethod) object and ask for its owner. So you could do method(:puts).owner and get Kernel.
To find which instance methods are defined on A (but not on superclasses):
A.instance_methods(false)
To find which instance methods are defined on A AND its superclasses:
A.instance_methods
To find which class (or module) a given method is defined on:
method(:my_method).owner
To find which object is the receiver for a given method:
method(:my_method).receiver
You can use Object#method. For example,
[1, 2, 3].method(:each_cons) # => #<Method: Array(Enumerable)#each_cons>
tells that the each_cons method of an Array comes from the Enumerable module.

How to show all methods of a class without ancestors methods in ruby?

To show all methods defined by a particular class, but without methods that are defined in ancestors classes, I'm writing like this.
foo.methods - foo.class.superclass.methods
Is there better way to do it?
You can get instance methods with the following:
foo.class.instance_methods(false)
as documented in http://ruby-doc.org/core-1.9.3/Module.html#method-i-instance_methods.
The documentation for the parameter uses the term "superclasses" in describing what is included if the parameter is truthy, but based on my testing I believe all ancestor-provided methods are excluded/included based on this value, not just those from superclasses.

Calling .methods on class vs instance in Ruby

Hoping to poll the collective consciousness here since I can't structure this in a way to find an answer via search. In Ruby 1.9+, calling .methods on an instance will yield different results than on the class of that instance. For example, "foo".methods will include 'length' and 'size' whereas String.methods will not. What is the reason for this? I am a veteran programmer but new to Ruby. From my understanding, methods is supposed to include all ancestor methods, so is it through a mixin or some other pattern that length and size are added into the instance's list but not the class's?
You're confusing .methods() with .instance_methods().
The first will give you the methods which can be invoked on the String object - that is the String class as an object itself. The second will give you the methods of objects created using the String class, or instances of String.
Length and size are String instance methods, why would they be included in a list of String's (a class) methods? Classes are objects and have their own methods.
In other words, you get the list of methods supported by the object you're calling it on. String is a class, so you get its specific class methods, plus class methods it inherits.
A string instance is an instance, so you get string's instance methods, and instance methods it inherits.

If I define a method in Ruby, does it belong to any class?

I have feeling, that if one defines a method
def test
puts 'Hi'
end
then there is a class to which this method belongs to (i.e. Unknown#test). So one probably has a possibility to list all methods defined "outside" of other classes. Or there is another way to do such listing?
If you define a method outside of any class, it will become a private method of the Object class.
A top-level method is a private method of Object.
Check out this question.
In future, to find what object a method belongs to, do this:
method(:test).owner
Output, for your example is Object
And you can then list all the methods of Object with
Object.send(:methods)
or
Object.send(:private_methods)

Resources