Ruby
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Methods and Blocks
-
Section 4: Object-Oriented Ruby
-
Section 5: Metaprogramming
-
Section 6: Working with Data and Files
-
Section 7: Ruby Frameworks Overview
-
Section 8: Ecosystem and Testing
-
Section 9: Practical Projects
-
Section 10: Interview Practice
-
Section 11: Data Structures and Algorithms in Ruby
-
Section 12: More Practice Exercises
-
Section 13: Enumerable and Functional Style
-
Section 14: More OOP Practice
-
Section 15: More Testing
-
Section 16: Enumerable and Comparable Modules In Depth
-
Section 17: Ruby Standard Library: Core Utilities
-
Section 18: Ruby Standard Library: Data and Security
-
Section 19: Ruby Standard Library: CLI and Text
-
Section 20: Ruby Networking
-
Section 21: Ruby on Rails Deep Dive
-
Section 22: Ruby Metaprogramming Deep Dive
-
Section 23: Ruby Design Patterns
-
Section 24: Ruby Concurrency
-
Section 25: Ruby Testing Deep Dive
-
Section 26: Ruby Gems and Packaging
-
Section 27: Ruby Performance
-
Section 28: More Practice Exercises
-
Section 29: More Interview Practice
-
Section 30: Rails API Development
-
Section 31: Rails Authentication and Authorization
-
Section 32: Rails Testing Deep Dive
-
Section 33: Rails Performance
-
Section 34: Rails Deployment
-
Section 35: Sinatra and Lightweight Ruby Web Apps
-
Section 36: More Ruby Language Deep Dive
-
Section 37: Ruby 3.x Modern Features
-
Section 38: More Data Structures in Ruby
-
Section 39: More Practical Projects
-
Section 40: Ruby Ecosystem Tools
-
Section 41: More Practice and Review
-
Section 42: Final Practice and Mastery
-
Section 43: Ruby Interview Deep Dive
-
Section 44: Ruby Background Processing Deep Dive
-
Section 45: Ruby GraphQL
-
Section 46: Ruby Object Model Deep Dive
-
Section 47: Ruby Hanami Framework Overview
-
Section 48: Ruby gRPC and Protocol Buffers
-
Section 49: Ruby Data Processing
-
Section 50: Ruby Search Integration
-
Section 51: Ruby File Upload and Media
-
Section 52: Ruby Email and Notifications
-
Section 53: Ruby Admin Panels
-
Section 54: Ruby Feature Flags and Experimentation
-
Section 55: Ruby Monitoring and Observability
-
Section 56: Ruby Docker and Deployment Deep Dive
-
Section 57: Ruby Security Deep Dive
-
Section 58: More Advanced Metaprogramming
-
Section 59: More Final Projects
13: Classes and Objects
Think about a blueprint for a house. The blueprint itself isn't a house—you can't sleep in it, you can't cook in the kitchen, and it doesn't keep you dry when it rains. It's just a set of instructions. However, using that one blueprint, a contractor can build ten different houses on the same street. Each house has the same basic layout, but one might be painted blue, another might have a red door, and one might have a family of four living in it while another is empty.
In Ruby, a Class is that blueprint. An Object (or an instance) is the actual house built from it. You define the logic once in the class, and then you can spawn as many unique objects as you need.
The Blueprint vs. The Machine
Let's move away from houses and look at something I use every morning: a coffee machine. If we were designing a CoffeeMachine class, we wouldn't want to write the code for "how to brew" every single time we bought a new machine. We define the idea of a coffee machine once.
class CoffeeMachine
# This is where the magic happens
end
Right now, this class doesn't do anything. It's just an empty shell. To make it useful, we need to give it "state" (data it remembers) and "behavior" (things it can do).
Setting the Initial State
When you take a coffee machine out of the box, it starts with certain settings. Maybe the water tank is empty, or it's set to "Medium" strength. In Ruby, we handle this in a special method called initialize. I like to think of this as the "setup" phase. Any variable starting with an @ symbol is an instance variable, meaning it belongs to that specific object, not the class as a whole.
class CoffeeMachine
def initialize(brand, water_level)
@brand = brand
@water_level = water_level
@beans_loaded = false
end
end
Now, when I create an object, I'm "instantiating" the class. I'm telling Ruby: "Use the CoffeeMachine blueprint to make a real object with these specific details."
my_machine = CoffeeMachine.new("BrewMaster", 100)
your_machine = CoffeeMachine.new("CafePod", 50)
Notice that my_machine and your_machine are completely separate. If I change the water level in mine, yours stays exactly where it was. They are independent objects born from the same blueprint.
Giving Your Object a Job to Do
A coffee machine that just sits there is just a plastic box. We need methods to define its behavior. These methods can interact with the instance variables we set up earlier. This is the core of Object-Oriented Programming: grouping the data (water level) and the logic (brewing) together in one place.
class CoffeeMachine
def initialize(brand, water_level)
@brand = brand
@water_level = water_level
@beans_loaded = false
end
def load_beans
@beans_loaded = true
puts "Beans are loaded into the #{@brand} machine!"
end
def brew
if @beans_loaded && @water_level >= 20
@water_level -= 20
puts "Sizzzz... Your coffee is ready! Water remaining: #{@water_level}%"
elsif !@beans_loaded
puts "Error: No beans! Please load beans first."
else
puts "Error: Not enough water!"
end
end
end
I've spent years seeing developers make the mistake of putting all their logic into one giant script. By wrapping this in a class, you've created a modular component. If you need to change how brew works, you change it in one place (the class), and every single coffee machine object in your entire program instantly gets the update.
📋 Practical Task
Build a Digital Pet Care Simulator
Your task is to create a DigitalPet class that simulates a simple virtual pet. Instead of just printing text, your object needs to manage its own internal state.
Requirements:
- The
initializemethod should take anameand aspecies. It should also set ahungerlevel to 50 (out of 100) and ahappinesslevel to 50. - Create a
feedmethod that decreaseshungerby 10. If hunger reaches 0, it should stay at 0. - Create a
playmethod that increaseshappinessby 10 but increaseshungerby 5 (playing makes the pet hungry!). - Create a
statusmethod that prints a summary of the pet's current state (e.g., "Bubbles the Goldfish is moderately hungry and very happy").
Testing your code: Create two different pets (e.g., a dog and a cat) and perform a series of actions on them. Verify that feeding the dog does not affect the cat's hunger level.
There are no comments for now.