A pipeline is essentially this
steps = [ ->(r) { r }, ->(r) { r }, ->(r) { r }, ]
Wrap initial data in a common Value object
initial = Result.new(some_data)
Run the Result through the steps, in order
result = steps.reduce(initial) { |r, step| step.call(r) }
That's the pattern, really. A reduce operation.
Re. stack trace, it can add noise because you're iterating over steps instead of calling them procedurally one by one, and you may want to decorate steps (put steps inside steps) for encapsulation, caching, etc. but again no different than Rack.