Solid::Process provides a callback system built on ActiveSupport::Callbacks that enables lifecycle hooks during process execution. Process-level callbacks are invoked by the Solid::Process::Caller module during the call lifecycle, while input-level callbacks are provided by Solid::Model and execute during initialization and validation.
For information about the overall process execution flow, see Process Lifecycle and Caller Module. For error handling patterns that work with callbacks, see Error Handling and Rescue Mechanisms.
The framework provides two distinct callback layers:
| Layer | Module | Callbacks | Execution Context |
|---|---|---|---|
| Process | Solid::Process::Callbacks | before_call, around_call, after_call, after_success, after_failure | Main process execution |
| Model/Input | Solid::Model | after_initialize, before_validation, after_validation | Input validation and initialization |
Callback System Architecture
Sources: lib/solid/process/caller.rb6-32 lib/solid/process/callbacks.rb1-35 lib/solid/model.rb31-40
Process-level callbacks are defined using Solid::Process::Callbacks and invoked by the Solid::Process::Caller module during execution.
The before_call callback executes within the run_callbacks(:call) block in Solid::Process::Caller, after input validation succeeds but before the user-defined call method.
before_call Execution in Caller
The callback has access to the process instance, including input and dependencies objects. It executes only when validation succeeds.
| Attribute | Access Pattern | Available Data |
|---|---|---|
| Input | input.attribute_name | Validated, type-cast attributes |
| Dependencies | dependencies.dep_name | Validated dependencies (if defined) |
| Process State | Instance variables | Any state set during initialization |
Sources: lib/solid/process/caller.rb11-20 lib/solid/process/callbacks.rb14-16 test/solid/process/callbacks/before_call_test.rb28-31
The around_call callback wraps the execution within the run_callbacks(:call) block. It receives the process instance and must yield to continue execution.
around_call Structure
Use cases for around_call:
Sources: lib/solid/process/callbacks.rb18-20 test/solid/process/callbacks/around_call_test.rb28-38
The after_call callback executes within the run_callbacks(:call) block after the user-defined call method completes, regardless of whether it returned Success or Failure.
This callback has access to the output attribute, which contains the final result.
| Attribute | Type | Content |
|---|---|---|
output | Solid::Result | The Success or Failure result returned by call |
output.success? | Boolean | Whether the result is a success |
output.failure? | Boolean | Whether the result is a failure |
output.type | Symbol | The result type (e.g., :user_created, :invalid_data) |
Sources: lib/solid/process/callbacks.rb22-24 test/solid/process/callbacks/after_test.rb62-72
After the :call callback chain completes, the Solid::Process::Caller module conditionally executes outcome-specific callbacks based on the result.
These callbacks execute outside the run_callbacks(:call) block, triggered by the result type:
Caller Outcome Dispatch
Callback Execution Order in Caller
From lib/solid/process/caller.rb11-31:
Line 11: run_callbacks(:call) do
Line 12-26: [input validation and call execution]
Line 27: end
Line 28: run_callbacks(:success) if output.success?
Line 29: run_callbacks(:failure) if output.failure?
Line 31: output
| Callback | Condition | Line in Caller | Access |
|---|---|---|---|
after_success | output.success? == true | 28 | output, input, dependencies |
after_failure | output.failure? == true | 29 | output, input, dependencies |
Sources: lib/solid/process/caller.rb28-29 lib/solid/process/callbacks.rb26-32 test/solid/process/callbacks/after_test.rb30-60
Callbacks support the if: option to conditionally control execution, using either lambda expressions or method symbols.
| Pattern | Example | Evaluation Context |
|---|---|---|
| Lambda | if: -> { output.type?(:user_created) } | Process instance |
| Method symbol | if: :should_notify? | Process instance method |
| Predicate method | if: :success? | Delegates to output.success? |
Conditional Evaluation Flow
Example conditional callback patterns from tests:
Sources: test/solid/process/callbacks/after_test.rb34-60
Multiple callbacks of the same type execute in the order determined by ActiveSupport::Callbacks. For after_* callbacks, this is reverse definition order (LIFO).
From test observations at test/solid/process/callbacks/after_test.rb92-98:
| Callback Type | Execution Order | Example |
|---|---|---|
after_success | Reverse definition (LIFO) | Defined [1, 2, 3] → Executes [3, 2, 1] |
after_failure | Reverse definition (LIFO) | Last defined executes first |
after_call | Reverse definition (LIFO) | Most recent first |
LIFO Execution Order
This LIFO behavior allows subclass callbacks to execute before parent class callbacks, enabling specialization without overriding parent behavior.
Sources: test/solid/process/callbacks/after_test.rb92-98
The Solid::Model module defines callbacks that execute during initialization and validation. Since Solid::Input includes Solid::Model, these callbacks are available in process input objects.
From lib/solid/model.rb31-40:
Line 31: extend ActiveModel::Callbacks
Line 33: define_model_callbacks :initialize, only: :after
Line 36-40: def initialize(...)
super
run_callbacks(:initialize)
end
| Callback | Definition Location | Execution Point | Access |
|---|---|---|---|
after_initialize | lib/solid/model.rb:33 | After super in initialize | Instance attributes |
before_validation | ActiveModel::Validations::Callbacks | Before validation runs | Mutable attributes |
after_validation | ActiveModel::Validations::Callbacks | After validation completes | Validated attributes |
Model Callback Execution Flow
These callbacks execute independently of process callbacks. During process execution, input callbacks run during the validation phase in Solid::Process::Caller.
Sources: lib/solid/model.rb31-40 test/solid/model/callbacks_test.rb14-24
The Solid::Process::Callbacks module defines three callback chains using ActiveSupport::Callbacks:
Callback Chain Definitions
From lib/solid/process/callbacks.rb5-11:
Line 6: include ActiveSupport::Callbacks
Line 8: included do
Line 9: define_callbacks :call, :success, :failure
Line 10: extend ClassMethods
Line 11: end
| Chain | Definition | Invoked By | Hooks Available |
|---|---|---|---|
:call | Line 9 | Caller#call line 11 | before_call, around_call, after_call |
:success | Line 9 | Caller#call line 28 | after_success |
:failure | Line 9 | Caller#call line 29 | after_failure |
Callback Definition to Execution Mapping
The ClassMethods module provides DSL methods (before_call, around_call, after_call, after_success, after_failure) that delegate to set_callback from ActiveSupport::Callbacks.
Sources: lib/solid/process/callbacks.rb5-35 lib/solid/process/caller.rb11-29
Callbacks enable several cross-cutting patterns:
around_callbefore_call and result logging with after_callafter_success, error alerts with after_failurebefore_validation in input classesThe callback system provides a clean separation of concerns, allowing business logic to remain focused while cross-cutting concerns are handled declaratively through the callback mechanism.
Sources: test/solid/process/callbacks/before_call_test.rb1-51 test/solid/process/callbacks/around_call_test.rb1-61 test/solid/process/callbacks/after_test.rb1-120
Refresh this wiki