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.


Comments(0)