Steps
Steps
Steps are the core components of a service, each representing a unit of work executed in sequence when the service is called.
TL;DR
Define steps using the
stepkeyword within the service classUse
ifandunlessoptions for conditional stepsInherit steps from parent classes
Inject steps into the execution flow with
beforeandafteroptionsEnsure cleanup steps run with the
always: trueoption (unlessdone!was called)Use a
runmethod as a simple alternative for single-step services
class GeneralParserService < ApplicationService
step :create_browser, unless: :browser
step :parse_content
step :quit_browser, always: true
end
class ParsePage < GeneralParserService
step :parse_additional_content, after: :parse_content
endDefine Steps
Steps are declared using the step keyword in your service class.
Conditional Steps
Steps can be conditional, executed based on specified conditions using the if or unless keywords.
This feature works well with argument predicates.
Using Procs for Conditions
You can also use Procs (lambdas) for inline conditions:
Inheritance
Steps are inherited from parent classes, making it easy to build upon existing services.
Injecting Steps into Execution Flow
Steps can be injected at specific points in the execution flow using before and after options.
Let's enhance the previous example by adding a step to send a notification after updating the record.
Combine this with if and unless options for more control.
Always Running Steps
To ensure certain steps run regardless of previous step outcomes (errors, warnings, failed validations), use the always: true option. This is particularly useful for cleanup tasks, error logging, etc.
Note: if done! was called, the service exits early and always: true steps will not run.
Early Exit with stop!
stop!Use stop! to stop executing remaining steps without adding an error. This is useful when you've completed the service's goal early and don't need to run subsequent steps.
You can check if stop! was called using stopped?:
Database Transactions: Calling stop! does NOT rollback database transactions. All database changes made before stop! was called will be committed.
Immediate Exit with stop_immediately!
stop_immediately!Use stop_immediately! when you need to halt execution immediately, even within the current step. Unlike stop!, code after stop_immediately! in the same step method will NOT execute.
stop_immediately! raises an internal exception to halt execution. Steps marked with always: true will NOT run when stop_immediately! is called.
Database Transactions: Calling stop_immediately! does NOT rollback database transactions. All database changes made before stop_immediately! was called will be committed.
Immediate Failure with fail_immediately!
fail_immediately!Use fail_immediately! when you need to halt execution immediately AND rollback any database transactions. Unlike stop_immediately!, this method adds an error and causes transaction rollback.
Database Transactions: Calling fail_immediately! DOES rollback database transactions. All database changes made before fail_immediately! was called will be rolled back.
Comparison Table
stop!
No
After current step
No
stop_immediately!
No
Immediately
No
fail!(msg)
Yes (:base)
After current step*
No
fail_immediately!(msg)
Yes (:base)
Immediately
Yes
*By default, adding an error stops subsequent steps from running due to break_on_add configuration.
Removing Inherited Steps
When inheriting from a parent service, you can remove steps using remove_step:
Using run Method as a Simple Alternative
run Method as a Simple AlternativeFor simple services that don't need multiple steps, you can define a run method instead of using the step DSL. If no steps are defined, Operandi will automatically use the run method as a single step.
This is equivalent to:
Inheritance with run Method
run MethodThe run method works with inheritance. If a parent service defines a run method, child services will inherit it:
What's Next?
Next step is to learn about outputs. Outputs are the results of a service, returned upon completion of service execution.
Last updated