All original content is created in Ukrainian. Not all content has been translated yet. Some posts may only be available in Ukrainian.Learn more

What is PORO in Ruby?

Post cover: What is PORO in Ruby?
Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
In Ruby, the term PORO (Plain Old Ruby Object) is often mentioned, but what is it and why is it important?

PORO: in simple terms

PORO is simply a regular Ruby object. It does not inherit from specific libraries or framework classes like ActiveRecord, ActionController, or others. A PORO is an object that:
  1. Is lightweight and minimalist.
  2. Has only the methods needed to solve a specific problem.
  3. Is independent of external frameworks or libraries.

Advantages of PORO

  • Simplicity: PORO helps keep the code clean and understandable.
  • Flexibility: You can use PORO in any Ruby project without being tied to frameworks.
  • Test coverage: PORO is easy to test since they have no dependencies on a complex framework ecosystem.

When to use PORO?

  1. When you need to implement specific business logic that doesn't fit into models, controllers, or helpers.
  2. When you want to create small, standalone classes.
  3. When you need to reduce dependency on frameworks and make the code more modular.
PORO is important for flexible design, as it allows the creation of independent components that do not rely on frameworks like Rails. For example, imagine business logic for calculating salaries. If it is tied to ActiveRecord, its use depends on access to the database. This complicates testing and limits the ability to reuse it in other contexts, such as APIs or microservices.
With PORO, you can extract logic into a separate object that works only with input data and has no ties to external dependencies. This approach simplifies testing, enhances code modularity, and allows for easy adaptation to new needs. This makes PORO an effective tool for creating a clean application architecture.

Using PORO in Rails

Imagine that in your Rails project, there is a need to calculate the total cost of an order:
class OrderTotalCalculator
  def initialize(order)
    @order = order
  end

  def total
    @order.items.sum { |item| item.price * item.quantity }
  end
end

# Usage:
order = Order.find(1) # Example of an ActiveRecord model
calculator = OrderTotalCalculator.new(order)
puts calculator.total
In this example, OrderTotalCalculator is a PORO. It is separated from Rails models and controllers, making it independent and easy to test.

How to test PORO?

Due to its simplicity, PORO is easy to test using RSpec or MiniTest:
RSpec.describe DiscountCalculator do
  it 'calculates the correct discounted price' do
    calculator = DiscountCalculator.new(100, 10)
    expect(calculator.final_price).to eq(90.0)
  end
end
PORO is the foundation of clean and simple design in Ruby. They (plain objects without dependencies) help create flexible, independent components that are easy to extend, maintain, and test.

This post doesn't have any additions from the author yet.

What does relational mean (in the context of relational databases)?
21 Sep 08:27

What does relational mean (in the context of relational databases)?

meme code
meme code@memecode
What is RDBMS (relational database management system)?
21 Sep 08:56

What is RDBMS (relational database management system)?

meme code
meme code@memecode
What does the ACID principle mean in programming?
24 Sep 20:31

What does the ACID principle mean in programming?

meme code
meme code@memecode
What is Convention over Configuration (in the context of RoR and beyond)?
26 Sep 07:47

What is Convention over Configuration (in the context of RoR and beyond)?

meme code
meme code@memecode
Rounding Decimal Numbers: Mathematical Rules, JavaScript, and Ruby
18 Oct 12:59

Rounding Decimal Numbers: Mathematical Rules, JavaScript, and Ruby

meme code
meme code@memecode
[Fix] Factory not registered: "user" (KeyError) (FactoryBot / Rails 7)
07 Dec 10:46

[Fix] Factory not registered: "user" (KeyError) (FactoryBot / Rails 7)

meme code
meme code@memecode
What is the difference between spec_helper.rb and rails_helper.rb in RSpec?
08 Dec 13:53

What is the difference between spec_helper.rb and rails_helper.rb in RSpec?

meme code
meme code@memecode
09 Dec 14:50

[Fix] No such file or directory @ rb_sysopen - tmp/pids/server.pid

meme code
meme code@memecode
What you need to know to build a successful freelance career in IT
23 Dec 16:03

What you need to know to build a successful freelance career in IT

meme code
meme code@memecode
Virtual cloud server: what it is and what makes it special
03 Jan 10:58

Virtual cloud server: what it is and what makes it special

meme code
meme code@memecode
[Fix] Heroku / SearchBox addon - indexing error "The client is unable to verify that the server is Elasticsearch"
31 Jan 13:09

[Fix] Heroku / SearchBox addon - indexing error "The client is unable to verify that the server is Elasticsearch"

meme code
meme code@memecode
06 Feb 15:31

Fix error [DEPRECATION] #adapters is deprecated. Use #profiles instead. (Codecov / docile)

meme code
meme code@memecode