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, type: Business # validate that output type is an instance of 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
Run the test suite against current Rails version:
bundle exec rake test
Run the test suite against all supported Rails versions using
bundle exec appraisal rake test
For help updating the
Gemfile or changing supported Rails versions, see the
appraisal gem README.
Note that the gemfiles in
gemfiles/* are auto-generated by
appraisal and should not be modified directly.