Skip to content

Instantly share code, notes, and snippets.

@mikeknep
Created June 29, 2016 16:21
Show Gist options
  • Save mikeknep/ce17385caacef7535625a2bf69b42640 to your computer and use it in GitHub Desktop.
Save mikeknep/ce17385caacef7535625a2bf69b42640 to your computer and use it in GitHub Desktop.
module Result
module Attempt
def self.start(&failable)
Success.new(nil).and_then(&failable)
end
end
end
module Result
class Failure
def initialize(error)
@error = error
end
def and_then
self
end
def finally(success: nil, failure: proc {})
failure.call(error)
end
private
attr_reader :error
end
end
describe "Result module" do
let(:x) { 1 }
class MyError < StandardError
end
class MyOtherError < StandardError
end
it "is explicitly started and concluded" do
output = Result::Attempt.start { x + 1 }.finally(success: ->(y) { y })
expect(output).to eq(2)
end
it "chains with #and_then" do
output = Result::Attempt.start { x + 1 }.
and_then { |y| y + 1 }.
and_then { |z| z + 1 }.
finally(success: ->(z) { z })
expect(output).to eq(4)
end
it "uses Failure class to catch failures" do
output = Result::Attempt.start do
raise MyError
end.finally(failure: ->(e) { e.to_s })
expect(output).to eq("MyError")
end
it "retains the first error" do
output = Result::Attempt.start do
raise MyError
end.
and_then { raise MyOtherError }.
finally(failure: ->(e) { e.to_s })
expect(output).to eq("MyError")
end
end
module Result
class Success
def initialize(arg)
@arg = arg
end
def and_then(&failable)
begin
Success.new(failable.call(arg))
rescue StandardError => e
Failure.new(e)
end
end
def finally(success: proc {}, failure: nil)
success.call(arg)
end
private
attr_reader :arg
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment