If you've ever thought how large-scale applications like Airbnb or Shopify are built and maintained, it's because of Object-Oriented Programming.
OOP is a programming paradigm that helps organize and manage complex code by breaking it down into reusable objects, making it easier to scale, debug, and maintain.
What is Object-Oriented Programming?
OOP is a way of organizing code into objects, where each object represents something real, like a car or a computer. These objects have their own data (attributes) and actions (methods).
The primary goal of OOP is to make code more organized, reusable, and easier to manage over time. Instead of writing repetitive code, you define blueprints (called classes) that can create multiple objects with similar properties.
A classic example of OOP's power is Don’t Repeat Yourself code, which saves time and reduces errors by reusing code efficiently.
The Four Pillars of OOP
OOP is built on four fundamental principles, often referred to as its pillars.
And they are Encapsulation, Inheritance, Polymorphism and Abstraction as well.
Encapsulation in Ruby
Encapsulation means bundling data and methods that operate on that data within a single unit, usually a class. It also restricts direct access to some of the object’s components, which helps protect the integrity of the object.
ruby
class Book
def initialize(title, author)
@title = title
@authоr = author
end
def display_details
"Title: #{@title}, Author: #{@authоr}"
end
end
book = Book.new("The Hobbit", "J.R.R. Tolkien")
puts book.display_details # Output: Title: The Hobbit, Author: J.R.R. Tolkien
Here, the @title and @authоr variables are encapsulated inside the Book class. They can't be accessed directly from outside the class.
Inheritance in Ruby
Inheritance allows a class to inherit attributes and methods from another class, reducing code duplication.
ruby
class Animal
def speak
"This animal makes a sound"
end
end
class Dog < Animal
def speak
"Bark!"
end
end
dog = Dog.new
puts dog.speak # Output: Bark!
In this example, the Dog class inherits from the Animal class but can also override its behavior.
Polymorphism in Ruby
Polymorphism allows objects to be treated as instances of their parent class, even if they behave differently. This makes code more flexible and easier to extend.
ruby
class Animal
def speak
"Animal sound"
end
end
class Cat < Animal
def speak
"Meow!"
end
end
class Dog < Animal
def speak
"Bark!"
end
end
animals = [Cat.new, Dog.new]
animals.each { |animal| puts animal.speak }
In this case, both Cat and Dog are treated as Animal objects, but they respond differently when asked to speak.
Abstraction in Ruby
Abstraction means hiding complex details from the user and exposing only essential features. It simplifies the interface and hides the implementation details.
You might write a class to handle complex database operations, but only expose a method like savetodb, which hides all the complexity from the user.
ruby
class Database
def save_to_db(data)
#Complex operations hidden here
"Data saved!"
end
end
db = Database.new
puts db.save_to_db("User Data") # Output: Data saved!
OOP in Ruby on Rails in Simple
Now let's see examples of each pillar of OOP in ruby on rails for better understanding. Let’s break it down with simple examples:
Encapsulation in Rails
In Rails, models are a great example of encapsulation. A model represents a table in the database and bundles the data (attributes) and methods that act on it.
Suppose you have a User model that stores user information and validates the user’s name.
ruby
class User < ApplicationRecord
validates :name, presence: true
def display_name
"Welcome, #{name}"
end
end
Here, validates ensures the user has a name. The method display_name is only available within the class, keeping the logic encapsulated inside.
Inheritance in Rails
Rails models automatically inherit from ApplicationRecord, which provides methods to interact with the database like find, save, and update.
ruby
class User < ApplicationRecord
end
user = User.find(1) # Finds a user with ID 1 from the database
Since User inherits from ApplicationRecord, it gets powerful database functionality without needing extra code.
Polymorphism in Rails
Polymorphism in Rails allows one model to work with different types of objects. A common example is a Comment model that can belong to a Post, Photo, or any other object.
ruby
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end
class Post < ApplicationRecord
has_many :comments, as: :commentable
end
class Photo < ApplicationRecord
has_many :comments, as: :commentable
end
Now, you can use the same Comment model to add comments to both posts and photos.
Abstraction in Rails
Abstraction in Rails means hiding complex details and exposing only the necessary parts. Rails does this through Active Record, which simplifies database interactions.
Instead of writing SQL queries like:
sql
SELECT * FROM users WHERE id = 1;
You can simply write in Rails:
ruby
user = User.find(1)
Rails handles the complex SQL behind the scenes, so you can focus on building features instead of writing database code and this is amazing.
To become a skilled Ruby on Rails developer, it's important to understand OOP.
Using OOP principles encapsulation, inheritance, polymorphism, and abstraction helps us write code that is easy to reuse, maintain, and understand.
If you're interested in learning more, check out Ruby on Rails Guides.
Let me know feedback in the comments below.