Hexagonal Architecture for Rails Developers

Why Do We Care About Architecture?

  • High-level abstract modules don’t depend upon low-level details.
  • Modules interact with each other via well-defined interfaces.
  • Modules can be developed and deployed independently.
  • The application becomes easy to test because the logic that needs to be tested depends upon neither the UI of the application nor the database. It also makes tests extremely fast.
  • Implementing another frontend (e.g., REST API) for the application becomes trivial.

Hexagonal Architecture

  • The Web UI and the database are external “devices”.
  • Controllers, all sorts of http clients, message queue clients are adapters.
  • The protocols of these http clients and message queue clients are ports.

Implementation Techniques

Example

class OrdersController < ApplicationController 
#...
def create
create_order = CreateOrder.new(OrderRepository, self)
create_order.create current_user, params[:order]
end
def order_creation_succeeded order
redirect_to order_path(order)
end
def order_creation_failed order
@order = order render 'new'
end
end
# Models
class User
#...
end
class Order
#...
end
# Adapters module OrderRepository
extend self
def save order
DATABASE.put(:order, id, order)
end
end
# Use Case Service
class CreateOrder
def initialize order_repository, listener
@order_repository = order_repository
@listener = listener
end
def create user, params
order = Order.new(params.merge(user: user))
if order.valid?
@order_repository.save(order)
@listener.order_creation_succeeded order
else
@listener.order_creation_failed order
end
end
end
  • External “devices”: the Web UI and the database.
  • Ports: The listener role that OrderController plays, and the protocol of OrderRepository.
  • Adapters: OrderController and OrderRepository.
  • Application: The User, Order models and the CreateOrder service.

Wrapping Up

  • The application knows nothing about Rails. Instead, it notifies listeners about the results of a use case execution.
  • The application knows nothing about persistence. It uses repositories to talk to the database.

Learn More

--

--

--

Nrwlio co-founder, Xoogler, Xangular. Work on dev tools for TS/JS. @NxDevTools and Nx Cloud architect. Calligraphy and philosophy enthusiast. Stoic.

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Victor Savkin

Victor Savkin

Nrwlio co-founder, Xoogler, Xangular. Work on dev tools for TS/JS. @NxDevTools and Nx Cloud architect. Calligraphy and philosophy enthusiast. Stoic.

More from Medium

Hunting down spooky JSON module redefinition via Oj

STOP drying up your code! — The overuse of DRY

Gems for your Ruby on Rails application to make testing fun

Building a Ruby Calculator