What happens when I create a class in Ruby?

That Ruby is strongly object-oriented is common knowledge. Everything is an object, from integers to the nil value. But what does that mean exactly? If everything is an object, what is the class of a class?

Let’s review for a moment the well-known syntax for creating a class:

classPersonendputsPerson.class.inspect# => Class

Ok, now that’s interesting. And what about the class of the Class class (I swear I’m not being confusing on purpose)?

That looks like the inspect of an instance! Does this mean that the inverse also works?

classklass;end# => SyntaxError: (eval):2: class/module name must be CONSTANT

Nope, it seems that the class syntax requires the name of the class to be a constant. Did you notice that the output of the variable klass when containing an instance of Class is very different than the ones we’re used to? That’s also related to constants:

It seems that the inspect method has a special case for constants. Now that explains a lot! That’s why when I forget to require some library or mistype a class I get this error:

putsPersno.inspect# => NameError: uninitialized constant Persno

When requiring a file, unless a namespace is defined, its constants are declared in the uppermost scope (which is Object btw), and that is why I’m able to access the class name independently of the scope I’m in:

# Accessing the class through the constantdefcreate_personPerson.newendputscreate_person.inspect# => #<Person:0x00000002dcd960># As opposed to receiving the class as an argument (since local# variables aren't visible outside of its local scope):defcreate_person(person_klass)person_klass.newendputscreate_person(klass).inspect# => #<#<Class:0x000000030714c8>:0x00000002c8ef68># This also works btw:putscreate_person(Person).inspect# => #<Person:0x00000002bcf618>

Did you notice when I said that the uppermost scope is Object? That has repercussions that may not be obvious at the first glance:

# Try opening IRB and typing this:putsself.inspect# => mainputsself.class.inspect# => Object# So does that mean...A_CONSTANT=1putsObject::A_CONSTANT.inspect# => 1Object::ANOTHER_CONSTANT=2putsANOTHER_CONSTANT.inspect# => 2# And that...classPersonendputsObject::Person.inspect# => Person# And since self is an instance of Object:putsself.class::Person.inspect# => Person

Since everything in Ruby is an object, meaning that it is a descendant of Object, any constants (or methods for that matter) declared in its scope are available everywhere. That’s awesome and explains so much!

Ok, we’ve been far enough that you must be wondering how does one define methods when instantiating a Class:

Person=Class.newdodefsay_hiputs"Hi"endendPerson.new.say_hi# => Hi

If you’ve been following closely you may be trying to figure out how does inheritance fits into all of this:

Great! That means that we can now completely ditch the old boring way of creating classes and use this! Should we? Of course not, it’ll only make you look like a smartass (like I must probably look right now), but it’s cool anyway:

That’s it for today folks, I think I exhausted everything that I could on this topic (aside from that damn Class.class.class.class… I’m certainly getting back to that someday). I love how Ruby seems to make perfect internal logic, like a well-written novel! Each and every piece of syntax can be simplified and eventually reduced to instantiating objects and calling methods, differently than languages like Java where some things simply… are the way they are.

Know other interesting quirks of the Ruby language? Did I make a mistake or made no sense at all? Send me a message and let me know! :)