Subroutine
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.
Example
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.
```ruby 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
Continue Reading
Development
Run the test suite against current Rails version:
bundle exec rake test
Run the test suite against all supported Rails versions using appraisal
:
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.