Trailblazer
Battle-tested Ruby framework to help structuring your business logic.
What's Trailblazer?
Trailblazer introduces new abstraction layers into Ruby applications to help you structure your business logic.
It ships with our canonical "service object" implementation called operation, many conventions, gems for testing, Rails support, optional form objects and much more.
Should I use Trailblazer?
Give us a chance if you say "yes" to this!
- You hate messy controller code but don't know where to put it?
- Moving business code into the "fat model" gives you nightmares?
- "Service objects" are great?
- Anyhow, you're tired of 12 different "service object" implementations throughout your app?
- You keep asking for additional layers such as forms, policies, decorators?
Yes? Then we got a well-seasoned framework for you: Trailblazer.
Here are the main concepts.
Operation
The operation encapsulates business logic and is the heart of the Trailblazer architecture.
An operation is not just a monolithic replacement for your business code. It's a simple orchestrator between the form objects, models, your business code and all other layers needed to get the job done.
# app/concepts/song/operation/create.rb
module Song::Operation
class Create < Trailblazer::Operation
step :create_model
step :validate
left :handle_errors
step :notify
def create_model(ctx, **)
# do whatever you feel like.
ctx[:model] = Song.new
end
def validate(ctx, params:, **)
# ..
end
# ...
end
end
The step
DSL takes away the pain of flow control and error handling. You focus on what happens: creating models, validating data, sending out notifications.
Control flow
The operation takes care when things happen: the flow control. Internally, this works as depicted in this beautiful diagram.
The best part: the only way to invoke this operation is Operation.call
. The single entry-point saves programmers from shenanigans with instances and internal state - it's proven to be an almost bullet-proof concept in the past 10 years.
result = Song::Operation::Create.(params: {title: "Hear Us Out", band: "Rancid"})
result.success? #=> true
result[:model] #=> #<Song title="Hear Us Out" ...>
Data, computed values, statuses or models from within the operation run are exposed through the result
object.
Operations can be nested, use composition and inheritance patterns, provide variable mapping around each step, support dependency injection, and save you from reinventing the wheel - over and over, again.
Leveraging those functional mechanics, operations encourage a high degree of encapsulation while giving you all the conventions and tools for free (except for a bit of a learning curve).
Tracing
In the past years, we learnt from some old mistakes and improved developer experience. As a starter, check out our built-in tracing!
result = Song::Operation::Create.wtf?(params: {title: "", band: "Rancid"})
Within a second you know which step failed - a thing that might seem trivial, but when things grow and a deeply nested step in an iteration fails, you will start loving #wtf?
! It has saved us days of debugging.
We even provide a visual debugger to inspect traces on the webs.
There's a lot more
All our abstraction layers such as operations, form objects, view components, test gems and much more are used in hundreds of OSS projects and commercial applications in the Ruby world.
We provide a visual debugger, a BPMN editor for long-running business processes, thorough documentation and a growing list of onboarding videos (TRAILBLAZER TALES).
Trailblazer is both used for refactoring legacy apps (we support Ruby 2.5+) and helps big teams organizing, structuring and debugging modern, growing (Rails) applications.
Documentation
- The current version is Trailblazer 2.1. We do have comprehensive API documenation ready for you. If you're new to TRB start with our LEARN page.
- A migration guide from 2.0 can be found on our website.
- The 1.x documentation is here.
Make sure to check out the new beginner's guide to learning Trailblazer. The new book discusses all aspects in a step-wise approach you need to understand Trailblazer's mechanics and design ideas.