A gem that provides an interface for creating feature-driven operations. You've probably heard at least one of these terms: "service objects", "form objects", "intentions", or "commands". Subroutine calls these "ops" and really it's just about enabling clear, concise, testable, and meaningful code.
So you need to sign up a user? or maybe update one's account? or change a password? or maybe you need to sign up a business along with a user, associate them, send an email, and queue a worker in a single request? Not a problem, create an op for any of these use cases. Here's the signup example.
class SignupOp < ::Subroutine::Op string :name string :email string :password string :company_name validates :name, presence: true validates :email, presence: true validates :password, presence: true validates :company_name, presence: true outputs :user outputs :business protected def perform u = create_user! b = create_business!(u) deliver_welcome_email(u) output :user, u output :business, b end def create_user! User.create!(name: name, email: email, password: password) end def create_business!(owner) Business.create!(company_name: company_name, owner: owner) end def deliver_welcome_email(u) UserMailer.welcome(u.id).deliver_later end end
So why use this?
- Avoid cluttering models or controllers with logic only applicable to one intention. You also don't need strong parameters because the inputs to the Op are well-defined.
- Test the Op in isolation
- Clear and concise intention in a single file
- Multi-model operations become simple