-
Notifications
You must be signed in to change notification settings - Fork 3
/
result.rb
89 lines (78 loc) · 1.81 KB
/
result.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
module Result
Success = Struct.new(
:success, # Boolean
:data # Additional response data
) do
def initialize(data = nil)
self.success = true
self.data = data
end
# Success a -> Result b
# Takes block of type (a -> Result b)
#
# Usage examples:
#
# ## Chaining queries
#
# ```ruby
# result = accounts_api.get(person_id, community_id).and_then { |account|
# payments_api.do_payment(payer: account[:payer_id])
# }
#
# if result[:success]
# flash t("successful.payment.to", result[:data][:receiver_id]
# else
# case result[:error_msg]
# when :paypal_servers_down
# # error message
# end
# end
#
# ## Map Success to Error
#
# ```ruby
# result = accounts_api.get(person_id, community_id).and_then { |account|
# if account[:payer_id].nil?
# Result::Error.new(:not_found)
# else
# payments_api.do_payment(payer: account[:payer_id])
# end
# }
def and_then(&block)
result = block.call(data)
result.tap do |res|
raise ArgumentError.new("Block must return Result") unless (res.is_a?(Result::Success) || res.is_a?(Result::Error))
end
end
# Success a -> Maybe a
#
# Usage example:
#
# account = accounts_api.get(person_id, community_id).maybe
# render(locals: { account_email: account[:email].or_else(nil) })
#
def maybe()
Maybe(data)
end
end
Error = Struct.new(
:success,
:error_msg,
:data
) do
def initialize(error_msg, data = nil)
self.success = false
self.error_msg = error_msg
self.data = data
end
# Error a -> Error a
# No-op
def and_then(&block)
self
end
# Error a -> None
def maybe()
Maybe(nil)
end
end
end