My Ruby newsletter is available here. Feel free to subscribe :-)

Ruby Object Model - Part 1

Ruby is a fully object-oriented programming language. But what does that really mean ?

In this series of articles, we’ll try to demystify the Ruby Object Model.

The Ancestor Chain

The ancestors method returns an Array that represents the ancestor chain.

The ancestor chain is the representation of the class hierarchy in Ruby.

In order, it contains:

  • The calling class
  • its included modules
  • its parent class
  • the included modules of its parents class
  • the parent class of its parent class
  • etc..

Here is an example of the ancestor chain of the Array class

irb> Array.ancestors                   # Array's ancestor chain
=> [Array, Enumerable, Object, Kernel, BasicObject]
irb> Array.included_modules # Array included modules
=> [Enumerable, Kernel]
irb> Array.superclass # the parent class
=> Object
irb> Array.superclass.included_modules # parent's included modules
=> [Kernel]
irb> Array.superclass.superclass # the grandparent class
=> BasicObject

Array::included_modules returns an array that contains all the modules included in the ancestor chain. This is why the Kernel module is included in the array for Array.included_modules.

Ancestor Chain and Method Call

When you call a method inside of your object, what Ruby does is to first check if this method exists inside the self context. If it doesn't find it there, it continues up the ancestor chain until it finds the method.

class Tiger
def to_s
"roar"
end
end
irb> Tiger.new.to_s
=> "roar" # calls the #to_s method defined in the Tiger class
irb> Tiger.inspect
=> "#<Tiger:0x007f>" # calls the #inspect method defined in Object

Object class hierarchy

Object is the default root class in Ruby. This means that any new class inherit from object by default

class Child
end
Child.superclass
=> Object

So, what’s the purpose of this class ?

If we call the ancestors method on Object it’ll return the following ancestor chain

irb> Object.ancestors
=> [Object, Kernel, BasicObject]

BasicObject

The BasicObject class is the top parent of all class. It contains a bare minimum of methods for object creation and object comparison.

Kernel

The Kernel module is included in the Object class. It contains all the “object manipulation” logic.

Object

As theKernel module contains the majority of the methods, Object is more used as an interface (for its name) by all its children.

The main object

When a new program starts, Ruby automatically creates the main object which is an instance of the Object class. main is the top-level context of any program. This is probably a nod to the C language (as the main() function is the entry point of any C program and that Matz loves C)

irb> self
=> main
irb> self.class
=> Object

main is the top-level scope of any ruby program. This means that any instruction out of a class/module scope is executed in the main context

irb> puts "main context"
=> main context

Here, the puts method refers to the private Kernel#puts method. We have access to this method because main is an instance of Object which includes Kernel .

Now, let’s explicitly try to access the puts method via self (which refers to the main object instance).

irb> self.puts "main context"
NoMethodError: private method `puts' called for main:Object

This error is due to the fact that a private method cannot be called with a receiver (self in this case).

Calling self.puts is like calling main.puts . So, We try to call puts outside of its class context.

In other words, we try to call a private method as a public one.

Conclusion

Ruby is a fully oriented-object language because from the entry point (the main context) to the end of your program you’ll be scoped at least in the main object.

Next article: If you don’t know that Module is an instance of the Class class, stored in a constant and whose instances cannot be instantiated then you’ll probably learn something :)

Voilà !


Thank you for taking the time to read this post :-)

Feel free to 👏 and share this Medium post if it has been useful for you.

Here is a link to my last medium post: 2 quick tips for IRB.

Like what you read? Give Mehdi Farsi a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.