RL ROLAND LOPEZ
// 2 min read

Ruby on Rails Object-Oriented Design

Maintainability is a design choice

Rails is opinionated, so it nudges you toward certain patterns. But there is still plenty of room for the decisions that decide how maintainable your app is later.

PS: most performance problems trace back to bad design choices.

The cost of poor design

Apps that start as a tight, interdependent mesh of objects get more expensive to maintain as they grow. Every new feature drags in more of the codebase.

The principle:

The cost of changing an app rises faster than its complexity.

A poorly designed example

# app/models/user.rb
class User < ApplicationRecord
  has_many :projects

  def total_project_hours
    projects.sum { |p| p.total_hours }
  end
end
# app/models/project.rb
class Project < ApplicationRecord
  belongs_to :user
  has_many :tasks

  def total_hours
    tasks.sum(:hours)
  end
end
class Task < ApplicationRecord
  belongs_to :project
end

Look at total_project_hours on User. It walks every project to add up hours.

That breaks the Single Responsibility Principle, since User should not own this, and it does in Ruby what SQL should do, so it slows down as projects grow.

The refactor

# app/models/user.rb
class User < ApplicationRecord
  has_many :projects
  has_many :tasks, through: :projects

  delegate :sum_hours, to: :tasks, prefix: :tasks
end
# app/models/project.rb
class Project < ApplicationRecord
  belongs_to :user
  has_many :tasks
end
class Task < ApplicationRecord
  belongs_to :project

  scope :sum_hours, -> { sum(:hours) }
end

Now total_project_hours is gone. You get the same number with:

  • @user.tasks_sum_hours

That is the total hours across all tasks in all of a user’s projects.

The calculation lives where the data lives, User stays focused, and SQL does the summing.

Takeaway

Good object-oriented design in Rails is not just following conventions. It is applying the principles that protect you from future change: keep responsibilities where the data is, and structure code so tomorrow’s feature touches fewer files.

Roland Lopez
Written by
Roland Lopez

Technical founder & AI crack-head

Built by Agent Skynet See the agency