It's the Ruby implementation of a railway-oriented programming concept. read more
The gem makes it super easy to control complex operations flow - the next step will happen only if the previous one was successful.
Ideally suited for handling task sequences that should be interrupted as soon as any subsequent task fails.
As not hard to guess, all is about chaining subsequent #chain
method calls to a ChainIt
instance.
The gem supports design-by-contract programming concept assuming ChainIt
will be used together with both #value
and #failure?
aware object that have to be returned by every #chain
related block. It is used to consider the operation successful or failed.
We recommend using Struct
:
Result = Struct.new(:success, :value) do
def failure?
!success
end
end
#initialize
- Initiates the operation. Auto exception handling mode is configurable here. (see examples section)
#chain
- Performs the code in its related block and memorizes the internal result value. This is done only when the state of the operation allows it.
#skip_next
- Skips the next #chain
call when it's block evaluates to true
.
#result
- The result of the operation representing success of failure.
auto_exception_handling
- default false
- Decide if any StandardError
exception should be rescued from any #chain
call. If so the rescued exception will be memorized as operation result object.
success = ->(value) { Result.new(true, value) }
ChainIt.new.
chain { success.call 2 }.
chain { |num| success.call(num * 2) }. # The operation result is passed as block argument if used.
result. #=> <struct Result success=true, value=4>
value #=> 4
failure = ->(value) { Result.new(false, value) }
ChainIt.new.
chain { success.call 2 }.
chain { failure.call 0 }. # All later steps calls will be skipped.
chain { success.call 4 }.
result. #=> <struct Result success=false, value=0>
value #=> 0
ChainIt.new.
chain { success.call 2 }.
skip_next { |num| num == 2 }. # The next chain will be skipped as the block evaluates to true.
chain { success.call 8 }.
result. #=> <struct Result success=true, value=2>
value #=> 2
ChainIt.new.
chain { raise StandardError.new }. #=> StandardError: StandardError
result.
value
ChainIt.new(auto_exception_handling: true).
chain { raise StandardError.new }.
result. #=> <StandardError: StandardError>
value #=> <StandardError: StandardError>
All the contributions are really welcome on GitHub at https://github.com/tier-tools/chainit according to the open-source spirit.
The gem is available as open source under the terms of the MIT License.