Description
Trailblazer is designed to handle different contexts like user roles by applying inheritance between and composing of operations, form objects, policies, representers and callbacks.
Wanna see some code? Jump right here!
Trailblazer alternatives and similar gems
Based on the "Abstraction" category.
Alternatively, view Trailblazer alternatives based on common mentions on social networks and blogs.
-
Interactor
Interactor provides a common interface for performing complex user interactions. -
wisper
A micro library providing Ruby objects with Publish-Subscribe capabilities -
Responders
A set of Rails responders to dry up your application -
ActiveInteraction
:briefcase: Manage application specific business logic. -
Decent Exposure
A helper for creating declarative interfaces in controllers -
Mutations
Compose your business logic into commands that sanitize and validate input. -
Rails Event Store
A Ruby implementation of an Event Store based on Active Record -
dry-types
Flexible type system for Ruby with coercions and constraints -
Light Service
Series of Actions with an emphasis on simplicity. -
Amoeba
A ruby gem to allow the copying of ActiveRecord objects and their associated children, configurable with a DSL on the model -
SimpleCommand
A simple, standardized way to build and use Service Objects (aka Commands) in Ruby -
Waterfall
A slice of functional programming to chain ruby services and blocks, thus providing a new approach to flow control. Make them flow! -
u-service
Represent use cases in a simple and powerful way while writing modular, expressive and sequentially logical code. -
Surrounded
Create encapsulated systems of objects and focus on their interactions -
PageletRails
Improve perceived performance of your rails application with minimum effort -
Smart Init - Simple service objects in Ruby
A simple gem for eliminating Ruby initializers boilerplate code, and providing unified service objects API -
Rocketman
๐ Rocketman help build event-based/pub-sub code in Ruby -
SuperModule
SuperModule allows defining class methods and method invocations the same way a super class does without using def included(base). This also succeeds ActiveSupport::Concern by offering lighter syntax -
skinny_controllers
A pattern for allowing for easier testing of large projects' business logic -
Invokable
Objects are functions! Treat any Object or Class as a Proc (like Enumerable but for Procs). -
Lionshare
A Ruby interface to the Lionshare API (cryptocurrency prices) -
EasilyTypable
Ruby module that facilitates English-like type checking in an inheritance hierarchy via "type_name?" methods -
grpc_serializer
A simple library to encode nested hash to grpc object and vice versa -
simple_active_link_to
Simple rails view helper to manage "active" state of a link -
dry-rb
dry-rb is a collection of next-generation Ruby libraries, each intended to encapsulate a common task.
Static code analysis for 29 languages.
* Code Quality Rankings and insights are calculated and provided by Lumnify.
They vary from L1 to L5 with "L5" being the highest.
Do you think we are missing an alternative of Trailblazer or a related project?
README
Trailblazer
Trailblazer provides new high-level abstractions for Ruby frameworks. It gently enforces encapsulation, an intuitive code structure and approaches the modeling of complex business workflows with a functional mind-set.
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 brand-new book discusses all aspects in a step-wise approach you need to understand Trailblazer's mechanics and design ideas.
Screencasts
Watch our series of screencasts TRAILBLAZER TALES if you prefer learning from videos!
Trailblazer In A Nutshell
- All business logic is encapsulated in operations (service objects).
- Controllers instantly delegate to an operation. No business code in controllers, only HTTP-specific logic.
- Models are persistence-only and solely define associations and scopes. No business code is to be found here. No validations, no callbacks.
- The presentation layer offers optional view models (Cells) and representers for document APIs.
- More complex business flows and life-cycles are modeled using workflows.
Want code? Jump right here!
Mission
While Trailblazer offers you abstraction layers for all aspects of Ruby On Rails, it does not missionize you. Wherever you want, you may fall back to the "Rails Way" with fat models, monolithic controllers, global helpers, etc. This is not a bad thing, but allows you to step-wise introduce Trailblazer's encapsulation in your app without having to rewrite it.
Trailblazer is all about structure. It helps re-organize existing code into smaller components where different concerns are handled in separated classes.
Again, you can pick which layers you want. Trailblazer doesn't impose technical implementations, it offers mature solutions for recurring problems in all types of Rails applications.
Trailblazer is no "complex web of objects and indirection". It solves many problems that have been around for years with a cleanly layered architecture. Only use what you like. And that's the bottom line.
Concepts over Technology
Trailblazer offers you a new, more intuitive file layout in applications.
app
โโโ concepts
โ โโโ song
โ โ โโโ operation
โ โ โ โโโ create.rb
โ โ โ โโโ update.rb
โ โ โโโ contract
โ โ โ โโโ create.rb
โ โ โ โโโ update.rb
โ โ โโโ cell
โ โ โ โโโ show.rb
โ โ โ โโโ index.rb
โ โ โโโ view
โ โ โ โโโ show.haml
โ โ โ โโโ index.rb
โ โ โ โโโ song.css.sass
Instead of grouping by technology, classes and views are structured by concept, and then by technology. A concept can relate to a model, or can be a completely abstract concern such as invoicing
.
Within a concept, you can have any level of nesting. For example, invoicing/pdf/
could be one.
Architecture
Trailblazer extends the conventional MVC stack in Rails. Keep in mind that adding layers doesn't necessarily mean adding more code and complexity.
The opposite is the case: Controller, view and model become lean endpoints for HTTP, rendering and persistence. Redundant code gets eliminated by putting very little application code into the right layer.
Routing
Trailblazer uses Rails routing to map URLs to controllers, because it works.
Rails.application.routes.draw do
resources :songs
end
Controllers
Controllers are lean endpoints for HTTP. They do not contain any business logic. Actions immediately dispatch to an operation.
class SongsController < ApplicationController
def create
run Song::Create # Song::Create is an operation class.
end
end
The #run
method invokes the operation. It allows you to run a conditional block of logic if the operation was successful.
class SongsController < ApplicationController
def create
run Song::Create do |op|
return redirect_to(song_path op.model) # success!
end
render :new # invalid. re-render form.
end
end
Again, the controller only dispatchs to the operation and handles successful/invalid processing on the HTTP level. For instance by redirecting, setting flash messages, or signing in a user.
Operation
Operations encapsulate business logic and are the heart of a Trailblazer architecture.
The bare bones operation without any Trailblazery is implemented in the trailblazer-operation
gem and can be used without our stack.
Operations don't know about HTTP or the environment. You could use an operation in Rails, Hanami, or Roda, it wouldn't know.
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.
class Song::Create < Trailblazer::Operation
step :model
step :validate
def model(ctx, **)
# do whatever you feel like.
ctx[:model] = Song.new
end
def validate(ctx, params:, **)
# ..
end
end
Operations define the flow of their logic using the DSL and implement the particular steps with pure Ruby.
You cannot instantiate them per design. The only way to invoke them is call
.
Song::Create.(params: {whatever: "goes", in: "here"})
Their high degree of encapsulation makes them a replacement for test factories, too.
Models
Models for persistence can be implemented using any ORM you fancy, for instance ActiveRecord or Datamapper.
In Trailblazer, models are completely empty. They solely contain associations and finders. No business logic is allowed in models.
class Song < ActiveRecord::Base
belongs_to :thing
scope :latest, lambda { all.limit(9).order("id DESC") }
end
Only operations and views/cells can access models directly.
Tests
In Trailblazer, you only have operation unit tests and integration smoke tests to test the operation/controller wiring.
Operations completely replace the need for leaky factories.
describe Song::Update do
let(:song) { Song::Create.(song: {body: "[That](http://trailblazer.to)!"}) }
end
Workflow
Operations are a great way to clean up controllers and models. However, Trailblazer goes further and provides an approach to model entire life-cycles of business objects, such as "a song" or "the root user" using workflow (pro feature
). Also, you don't have to use the DSL but can use the editor
instead (cool for more complex, long-running flows). Here comes a sample screenshot.
Installation
The obvious needs to be in your Gemfile
.
gem "trailblazer"
gem "trailblazer-rails" # if you are in rails.
gem "trailblazer-cells"
Cells is not required per default! Add it if you use it, which is highly recommended.