https://github.com/datacrafts-io/stepped
Make your services running step-by-step with error handling, logging and easy testing.
https://github.com/datacrafts-io/stepped
gem ruby stepped tools
Last synced: 16 days ago
JSON representation
Make your services running step-by-step with error handling, logging and easy testing.
- Host: GitHub
- URL: https://github.com/datacrafts-io/stepped
- Owner: datacrafts-io
- License: mit
- Created: 2020-07-28T10:29:38.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2022-04-25T19:12:10.000Z (about 3 years ago)
- Last Synced: 2025-03-25T21:11:17.772Z (about 1 month ago)
- Topics: gem, ruby, stepped, tools
- Language: Ruby
- Homepage:
- Size: 10.7 KB
- Stars: 5
- Watchers: 7
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README

# Make your services Stepped
## Installation
add to your Gemfile:
```ruby
gem "stepped", github: "datacrafts-io/stepped"
```## Usage
#### 1. `include Stepped` into your service
```ruby
class ClassName
include Stepped...
end
```#### 2. Use `param` and `option` keywords to define initial arguments:
```ruby
class ClassName
...param :argument_name, # reader name
->(value) { value.to_s }, # optional proc for type coercing
default: -> { "some string" } # optional proc with default value...
end
```
`param` is used to define arguments, `option` is for keyword arguments#### 3. Define the Steps:
- passed params and options are accessed in step blocks
- by default steps are passing result to next step
- set optional `pass: false` to cancel passing result of current step to next
- set optional `cache: true` to save result of current step and access it in another steps later via `step_result(:step_name)`
- set optional `from: :step_name` to receive arguments from `:step_name` instead of previous step (must be combined with `cache: true` for `from` step)
- set optional error handler on step `on_failure: [handler]`, `[handler]` is `Proc` or `:method_name` receiving 2 arguments: `:step_name` and `error` instance
```ruby
class ClassName
...step :step_one, cache: true do
puts "I'm the step one"
"Result of Step One"
endstep :step_two, on_failure: ->(_, err) { ... } do |result_of_prev_step|
puts result_of_prev_step # => Result of Step One
endstep :step_three, from: :step_one do |result_of_step_one|
puts result_of_prev_step # => Result of Step One
end...
end
```#### 4. Set optional `on_failure` options (default: `on_failure stop: false, reraise: true`):
First optional argument can be `:method_name` or `Proc`:
```ruby
class ClassName
...on_failure :error_handler, stop: true, # stop process on error
reraise: true # reraise error after error handlingdef error_handler(step_name, error)
Notifier.call(step_name, error.message)
end...
end
```#### 5. Use optional logger settings for debug or logging:
```ruby
class ClassName
...logger on_start: true, # => [Stepped] Started ClassName with arguments: (arguments below)
before_step: true, # => [Stepped] Step [step_name] received: (arguments below)
after_step: true, # => [Stepped] Step [step_name] passed: (arguments below)
on_end: true, # => [Stepped] ClassName finished and returned: (arguments below)
method: Rails.logger.method(:info) # method, proc, service, etc which has method :call with one arg...
end
```#### 6. Add optional wrapper:
Wrap all steps in block provided by passed arg```ruby
class ClassName
...wrap ActiveRecord::Base.method(:transaction) # pass something which has method :call and can receive block
...
end
```## Example usage:
```ruby
# define class
class CreateUser
include Steppedparam :attributes
option :available_points, proc(&:to_i), default: -> { 0 }on_failure :notify
step :create_user, cache: true do
User.create!(attributes)
endstep :send_email do |user|
UserMailer.send_welcome_email(user)
endstep :assign_points, from: :create_user do |user|
user.add_points(available_points)
user
endstep :notify do |user|
SlackNotifier.user_created(user)
endprivate
def notify(step_name, error)
SlackNotifier.user_create_error(error)
end
end# use
attributes = { name: "John", email: "[email protected]" }service = CreateUser.new(attributes, available_points: 5)
service.call# or shortly
CreateUser.call(attributes, available_points: 5)
```