Recently we released a bunch of updated Trailblazer gems and along with those the trailblazer
framework 2.1.2.
Loops in Operation
It felt great to close several pull requests that were asking for (or even adding) support to iterate over datasets in TRB, basically an each do ... end
for operations.
Integrating the features added by our fellow users with internal advanced mechanics such as tracing or patching took its time, that's why the "simple" PR sat there quite a while.
module Song::Operation
class Cover < Trailblazer::Operation
step :model
step Each(dataset_from: :composers_for_each) {
step :notify_composers
# more steps here or Subprocess()
}
step :rearrange
def composers_for_each(ctx, model:, **)
model.composers
end
# ...
end
end
The Each()
macro allows you to specify where the data set is coming from, and will then run the provided block (or another operation) for each item at runtime.
Assuming we had three composers
in the data set when we invoke the operation, the nested code is run subsequently as if there were three dedicated notify_composers
steps.
class Cover < Trailblazer::Operation
step :model
step :notify_composers.0
step :notify_composers.1
step :notify_composers.2
step :rearrange
We added features such as collecting values from the iterated block or input/output filtering, all described in the newly added docs.
Speaking of, we moved the macro docs to an entirely new section, and rewrote docs for Wrap()
as they were pretty basic before.
One thing I particularly love about this new macro is that it integrates nicely with our debugging API. You can even see in which iteration an error occurred! Check the trace below.
Using Ruby's "native" each
, this'd be a PITA to debug.
Your input on Each()
is crucial - feel free to chat to us at any time.
Composable input/output
In former versions of Trailblazer, we had the :input
and :output
option to define what comes in and goes out of a step.
class Create < Trailblazer::Operation
# ...
step :validate,
input: [:params], # pass :params into the step
output: [:result] # only let :result out!
end
Variable mapping - as this is called in Trailblazer - is, after nesting, the most commonly used feature of the framework.
Good news: we are not dropping support for :input
and :output
! However, this is now superseded by "composable" variable mapping. On first glance, nothing much has changed.
step :validate,
In() => [:params],
Out() => [:result]
Well, we replaced the :symbol
option with In()
, Out()
, and Inject()
. However, this comes in handy if you want to add or alter variable mapping that has been defined formerly, for example in a macro.
step Validate(), # adds In() and maybe Inject()
In() => [:current_user] # we can add this on top!
You can even override and alter inherited variable mapping in a subclass.
class Upsert < Create
step :validate_for_upsert,
replace: :validate, # override inherited #validate step.
inherit: [:variable_mapping], # inherit filters from Create.
Inject() => [:current_user] # add this on top.
The entire approach with composable filters is extremely flexible and helps reducing bulky input/output code.
Introspect your filter chains
While this might look like a syntax touch-up, and, yes, anoooother API change, this brings us not only better structural features, but we can now introspect filter chains with the developer
gem.
puts Trailblazer::Developer.render(Create, :validate)
This renders the taskWrap and along with it the input and output filter chain. We even combine that with our upcoming IDE.
Note that this is not the final introspect API, though!
The code for variable mapping sits in the dsl-linear
gem and got some love, again. It is much easier to follow (and about 1/3 faster!) so maybe have a peek and add whatever you're missing?
You can find brand-new docs on our website.
Debugger and IDE
When working on Reform 3 and Each()
I used Trailblazer's debugging tools frequently and while benefiting from wtf?
and friends, we decided to improve the internal debugging API.
This turned into a bare-bones IDE that allows you to traverse through the trace of a deeply nested operation.
You can trace the incoming and outgoing ctx for each step, and even inspect its compiled taskWrap - where you can see the variable mapping chain!
The IDE will be a service launched by us in 2023.
What's next
Don't get me started, I could keep talking for hours! Anyhow, let's wrap this up.
- Reform 3 is coming, we're pretty close to a presentable version. It is entirely built with Trailblazer, so tracing, variable mapping, extendability and all things TRB come for free!
- The
endpoint
gem will get a stable release, promised! - More Trailblazer Tales are planned, sorry for the long interruption! Next topics will be nesting, variable mapping and the Wiring API.
We're looking forward to your feedback! I deleted Twitter and live on Mastodon now. Cheers and happy holidays!
Top comments (0)