This provides the tool which is implementation of railway-oriented programming concept itself (Read more on this here).
Ideally suited for executing task sequences that should be immediately interrupted when any subsequen task fails.
Everything comes down to chaining subsequent #chain
method calls to a ChainIt
object instance.
The gem supports design-by-contract programming concept - assuming every block related to #chain
have to return both #value
and #failure?
aware object.We reccomend using Struct for that purpouse.
Result = Struct.new(:success, :value) do
def failure?
!success
end
end
# Basic flow explanation
success = ->(value) { Result.new(true, value) }
ChainIt.new.
chain { success.call 2 }. #=> The subsequent chain will be triggered
chain { |num| success.call(num * 2) }. #=> We can pass the previous block evaluation as the block argument
chain { |num| success.call(num * 2) }.
result.
value #=> 8
# Working with #skip_next
ChainIt.new.
chain { success.call 2 }.
skip_next { |num| num == 2 }. #=> The next chain will be skipped conditionally since block returns true
chain { success.call 8 }.
chain { |num| success.call(num * 2) }. #=> The block argument is the last executed #chain value
result.
value #=> 4
# Dealing with a failure
failure = ->(value) { Result.new(false, value) }
ChainIt.new.
chain { success.call 2 }.
chain { failure.call 0 }. #=> All later #chain calls will be skipped
chain { success.call 4 }.
result.
value #=> 0
Bug reports and pull requests are welcome on GitHub at https://github.com/spark-solutions/chain_it.
The gem is available as open source under the terms of the MIT License.