It is best practice to separate your business logic into Service Objects rather than shoving all of it into your controllers and models. This keeps each layer focused: controllers handle HTTP, models handle persistence, and services orchestrate the actual work.
One solution we really like is ActiveInteraction. It is very stable, has wonderful documentation, and gives you a clean way to build service objects with support for things like composed interactions and even ActiveModel validations.
Add the gem to your Gemfile and run bundle install:
# Gemfile
gem "active_interaction", "~> 5.3"Create a base ApplicationInteraction class that all of your service
objects can inherit from. This gives you a single place to add shared
behavior later:
# app/interactions/application_interaction.rb
class ApplicationInteraction < ActiveInteraction::Base
# Your interactions will inherit from this class!
endEach interaction declares its inputs with typed filters, runs validations,
and implements an execute method. Here is a small example:
# app/interactions/users/sign_up.rb
module Users
class SignUp < ApplicationInteraction
string :email
string :name
validates :email, presence: true
def execute
User.create!(email: email, name: name)
end
end
endCall it with .run (which returns an outcome you can check) or .run!
(which raises on failure):
outcome = Users::SignUp.run(email: "ada@example.com", name: "Ada")
if outcome.valid?
user = outcome.result
else
# outcome.errors holds the validation messages
endBecause interactions support composed interactions, you can call one
service from another with compose, building larger workflows out of
small, well-tested pieces.
Create virtual credit / debit cards to keep your real info safe.
Get $5 when you sign up — free to start!
Everything you need to grow your business with confidence!
CRM, Lead Generation, Project Management, Contracts, Online Payments, and more!
The ads above are affiliate links to products I regularly use and highly
recommend.
I may receive a commission if you decide to purchase.