LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 520 min read

Everything Is an Object

Understand Ruby's pure object model — why numbers, strings, and even nil are real objects with real methods, and what that unlocks.

Introduction

This is the single most important lesson in this course. In many languages, a number or a boolean is a "primitive" — a special, lightweight value that isn't a real object and has no methods of its own. Ruby rejects that distinction entirely: everything, without exception, is a genuine object.

What You Will Learn
  • How to call methods directly on numbers, strings, and other values you might expect to be "primitives."
  • How method chaining lets you compose several operations into one readable expression.
  • Why even nil is a real object, and what that means in practice.
  • What duck typing is, and how it relates to Ruby's object model.

Calling Methods on "Primitives"

Because a plain integer is a real object, it has real, callable methods — no wrapper class or special syntax required.

puts 5.times.to_a # [0, 1, 2, 3, 4]
puts (-7).abs # 7
puts 3.14.round # 3
puts "hello".upcase # HELLO
puts "hello".reverse # olleh
Output

Click Run to see what this code prints.

5.times { ... }, seen throughout this course's examples, is exactly this same mechanism — 5 is an Integer object, and .times is simply one of the many methods that object provides.

Method Chaining

Because calling a method on an object often returns another object, you can chain multiple method calls together in one readable expression — a style that appears constantly in idiomatic Ruby.

result = " Hello, Ruby World! ".strip.downcase.split(" ").first
puts result
Output

Click Run to see what this code prints.

Reading right to left through the chain: .strip removes surrounding whitespace, .downcase lowercases it, .split(" ") turns it into an array of words, and .first grabs the first one — four operations, one clean line.

nil Is an Object Too

Even nil — Ruby's representation of "no value" — is an object of its own class, NilClass, with its own methods, including a very commonly used one: .nil?

value = nil
puts value.class # NilClass
puts value.nil? # true
puts value.to_s # "" (an empty string)
puts value.to_a # [] (an empty array)
Output

Click Run to see what this code prints.

Why This Matters in Practice

Because nil responds to methods like .to_s and .to_a instead of crashing immediately, some code that would raise a null-pointer-style error in other languages behaves predictably in Ruby — though calling a method nil truly doesn't support (like .upcase) still raises a clear NoMethodError.

Discovering Methods with .methods

Because every object carries its own list of available methods, you can ask any object what it can do — genuinely useful while learning or exploring an unfamiliar object.

puts 42.respond_to?(:times) # true
puts "hello".respond_to?(:times) # false
Output

Click Run to see what this code prints.

Duck Typing

Ruby's object model, combined with its dynamic typing, leads naturally to "duck typing" — the idea that an object's suitability for a task is judged by whether it responds to the methods you need, not by its declared type. "If it walks like a duck and quacks like a duck, treat it like a duck."

def describe_length(item)
puts "Length is #{item.length}"
end
describe_length("hello") # String responds to .length
describe_length([1, 2, 3]) # Array responds to .length too
Output

Click Run to see what this code prints.

Common Mistakes

Avoid These Mistakes
  • Treating Ruby's numbers and booleans as lightweight primitives out of habit from another language — in Ruby, they're genuinely full objects.
  • Calling a method on a value that might be nil without checking first, and being surprised by a NoMethodError.
  • Chaining so many methods together that a line becomes hard to read — chaining is a style choice, not an obligation.

Best Practices

  • Use value.nil? to check for "no value" explicitly rather than relying only on Ruby's general truthy/falsy rule when clarity matters.
  • Use method chaining for a clear, linear sequence of transformations, but break longer chains into named intermediate steps if readability suffers.
  • Lean into duck typing rather than manually checking is_a?(SomeClass) everywhere — Ruby idiomatically favors "does it respond to what I need," not "is it exactly this type."

Frequently Asked Questions

There is some overhead compared to languages with true unboxed primitives, though modern Ruby (with YJIT, covered in lesson 2) has narrowed that gap significantly for many real workloads.

No — the concept appears in Python and other dynamically typed languages too, but Ruby's pure object model and flexible method-based style make it an especially natural fit.

Ruby raises a NoMethodError at runtime, naming the exact method and object type involved — a common and usually easy-to-fix error while learning.

Key Takeaways

  • Every value in Ruby, including numbers and booleans, is a real object with callable methods.
  • Method chaining composes several operations into one readable expression.
  • nil is a real object (NilClass) with its own methods, including the commonly used .nil?
  • Duck typing judges an object by whether it responds to needed methods, not by its declared type.

Summary

Ruby's pure object model is why its code so often reads as a fluent chain of small, clear operations rather than a wall of separate statements. Next, you'll cover control flow: if/unless, loops, and Ruby's distinctive statement modifiers.

Next Lesson →

Control Flow