SOLID Ruby Code with Pub/Sub
If you are a programmer, very likely you've heard of pub/sub.
Today I am going to show you how this pattern can be useful when applied with one of the SOLID principles.
Imagine we have a user approval feature. After approving a user, an email must be sent and a job be triggered.
class UserApprovalsController < ApplicationController
def create
# ..
UserApproval.new(user).call
end
end
class UserApproval
def initialize(user)
@user = user
end
def call
@user.approve!
send_email
trigger_job
end
private
def send_email
WelcomeMailer.notify(@user).deliver_later
end
def trigger_job
HardWork.perform_later(@user)
end
end
This code may seem ok, but the UserApproval
class is doing so much and breaking the single responsibility principle (SRP), with time it can turn into a mess.
Let's refactor it to use the pub/sub pattern (through the Wisper gem):
class UserApprovalsController < ApplicationController
def create
# ..
user.approve!
end
end
class User < ActiveRecord::Base
include Wisper::Publisher
def approve!
update(status: :approved)
broadcast(:user_approved, self)
end
end
Here I removed the UserApproval
class and I am calling the approve!
method directly on controller.
This method just updates the instance and broadcasts a message with a payload.
class NotifierListener
def user_approved(user)
WelcomeMailer.notify(user).deliver_later
end
end
class HardWorkListener
def user_approved(user)
HardWork.perform_later(user)
end
end
So, two distinct classes (subscribers) are responsible for doing just one thing each.
Our code now has less complexity, it's easier to test and maintain.
See you.