This document explains the Steps DSL provided by Solid::Process for expressing multi-step workflows and composing processes together. The Steps DSL implements a railway-oriented programming model where each step can continue the flow or short-circuit with a result.
Related Pages:
call method, see Solid::Process - The Core AbstractionThe Steps DSL provides four core methods for chaining operations together in a process's call method:
| Method | Purpose | Return Behavior |
|---|---|---|
Given(hash) | Starts the step chain with initial data | Returns a Solid::Result containing the data |
and_then(:method_name) | Calls a private method if previous result was successful | Skips on Failure, executes on Success |
Continue(hash) | Merges data into the accumulated result and continues | Returns a Solid::Result for chaining |
and_expose(:type, [:keys]) | Finalizes the chain with a Success containing only specified keys | Returns Success(:type, ...) |
Sources: docs/REFERENCE.md607-621 docs/overview/030_INTERMEDIATE_USAGE.md1-61
Sources: docs/REFERENCE.md662-670 docs/overview/030_INTERMEDIATE_USAGE.md9-42
Given(hash) initiates a step chain by wrapping the provided hash in a Solid::Result object. It serves as the entry point for railway-oriented flow control.
Typical Usage:
The attributes parameter is the validated input hash passed from the process invocation. Given makes this data available to subsequent steps.
Sources: docs/REFERENCE.md632-633 docs/REFERENCE.md664
and_then(:method_name) calls a private instance method if the previous result was successful. If the previous result was a Failure or Success (not Continue), the chain short-circuits and that result becomes the final output.
Step methods invoked via and_then must:
** splat operator to ignore extra keysContinue(), Success(), or Failure()Example Step Method:
The ** splat is essential because the accumulated data hash may contain keys the current step doesn't need.
Sources: docs/REFERENCE.md617-618 docs/REFERENCE.md674-679
Sources: docs/REFERENCE.md709-717
Continue(hash) serves two purposes:
and_then to proceed to the next stepThe merged data becomes available to all subsequent steps in the chain.
Sources: docs/REFERENCE.md618 docs/REFERENCE.md695-703
Returning Success(:type, ...) or Failure(:type, ...) from a step immediately stops the chain. The result bypasses all remaining and_then calls and becomes the process's final output.
Sources: docs/REFERENCE.md681-693 docs/REFERENCE.md695-703
and_expose(:type, array_of_keys) creates the final Success result with only the specified keys from the accumulated data. This prevents leaking internal data to callers.
Example:
The first argument is the result type symbol. The second argument is an array of keys to extract from the accumulated data.
Sources: docs/REFERENCE.md619-621 docs/REFERENCE.md705-717
Sources: docs/REFERENCE.md623-659 docs/overview/030_INTERMEDIATE_USAGE.md11-41
Process composition allows building complex workflows by calling one process from within another. The deps block facilitates this by declaring process dependencies.
Sources: docs/REFERENCE.md933-982 docs/overview/040_ADVANCED_USAGE.md
When calling a process from within a step, you must explicitly handle the nested result using pattern matching or conditional logic.
Key Points:
deps.user_creation.call(owner) invokes the nested processSolid::Success extracts data from the nested resultContinue(user: user, user_token: token) merges nested data into parent flowSolid::Failure wraps the nested errorSources: docs/REFERENCE.md940-982
When a nested process fails, wrap its failure type to provide context about which operation failed:
This creates a hierarchical failure structure:
:invalid_owner (what failed)Example nested failure:
Callers can match specific nested failures:
Sources: docs/REFERENCE.md985-1007
The rollback_on_failure block wraps steps in an ActiveRecord transaction. If any step returns Failure, the transaction rolls back.
Rollback Behavior:
create_owner returns Failure, user creation is rolled backcreate_account fails, both user and account are rolled backlink_owner fails, all three operations are rolled backSources: docs/REFERENCE.md940-982 docs/REFERENCE.md723-823
Sometimes only part of the workflow should be transactional. Use .then to wrap specific steps:
This pattern:
Sources: docs/REFERENCE.md773-810
Sources: docs/REFERENCE.md933-1038
The Steps DSL implements railway-oriented programming where:
Continue() and proceedsFailure short-circuits the chainSuccess (not Continue) ends the chainSources: docs/REFERENCE.md662-670 docs/overview/030_INTERMEDIATE_USAGE.md46-53
| DSL Method | Code Location | Returns |
|---|---|---|
Given() | Available in Solid::Process#call instance method | Solid::Result (Success) |
and_then(:symbol) | Method on Solid::Result instance | Calls private instance method, returns its result |
Continue() | Available in private step methods | Solid::Result (Success with :continue type) |
Success(:type, hash) | Available in private step methods | Solid::Success instance |
Failure(:type, hash) | Available in private step methods | Solid::Failure instance |
and_expose(:type, array) | Method on Solid::Result instance | Solid::Success instance |
rollback_on_failure | Available in Solid::Process#call instance method | Returns a Solid::Result |
Sources: docs/REFERENCE.md613-621 lib/solid/process/version.rb4
Steps can return early Success to make processes idempotent (safe to call multiple times):
Benefits:
Sources: docs/REFERENCE.md681-693
** Splat in Step MethodsAlways include ** in step method signatures to ignore unused keys:
Each step should perform one logical operation:
and_expose to Limit Exposed DataOnly expose keys that callers need:
Provide context when propagating nested failures:
Sources: docs/REFERENCE.md674-679 docs/REFERENCE.md985-1007
Test step methods directly by invoking them with test data:
Inject fake dependencies to test composition in isolation:
Sources: docs/REFERENCE.md1693-1729
The Steps DSL provides a structured way to express complex workflows:
Process composition enables building hierarchical workflows by:
depsThis architecture promotes:
Sources: docs/REFERENCE.md607-1038 docs/overview/030_INTERMEDIATE_USAGE.md docs/overview/040_ADVANCED_USAGE.md
Refresh this wiki