errgonomic 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +11 -1
- data/Rakefile +8 -4
- data/doctest_helper.rb +3 -0
- data/flake.nix +16 -10
- data/gemset.nix +186 -21
- data/lib/errgonomic/core_ext/blank.rb +4 -4
- data/lib/errgonomic/option.rb +358 -0
- data/lib/errgonomic/presence.rb +92 -0
- data/lib/errgonomic/result.rb +316 -0
- data/lib/errgonomic/type.rb +67 -0
- data/lib/errgonomic/version.rb +1 -1
- data/lib/errgonomic.rb +44 -42
- metadata +36 -1
@@ -0,0 +1,316 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Errgonomic
|
4
|
+
module Result
|
5
|
+
# The base class for Result's Ok and Err class variants. We implement as
|
6
|
+
# much logic as possible here, and let Ok and Err handle their
|
7
|
+
# initialization and self identification.
|
8
|
+
class Any
|
9
|
+
attr_reader :value
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
# Equality comparison for Result objects is based on value not reference.
|
16
|
+
#
|
17
|
+
# @param other [Object]
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# Ok(1) == Ok(1) # => true
|
21
|
+
# Ok(1) == Err(1) # => false
|
22
|
+
# Ok(1).object_id == Ok(1).object_id # => false
|
23
|
+
# Ok(1) == 1 # => false
|
24
|
+
# Err() == nil # => false
|
25
|
+
def ==(other)
|
26
|
+
return false if self.class != other.class
|
27
|
+
|
28
|
+
value == other.value
|
29
|
+
end
|
30
|
+
|
31
|
+
# Indicate that this is some kind of result object. Contrast to
|
32
|
+
# Object#result? which is false for all other types.
|
33
|
+
#
|
34
|
+
# @example
|
35
|
+
# Ok("a").result? # => true
|
36
|
+
# Err("a").result? # => true
|
37
|
+
# "a".result? # => false
|
38
|
+
def result?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return true if the inner value is an Ok and the result of the block is
|
43
|
+
# truthy.
|
44
|
+
#
|
45
|
+
# @param [Proc] block The block to evaluate if the inner value is an Ok.
|
46
|
+
#
|
47
|
+
# @example
|
48
|
+
# Ok(1).ok_and?(&:odd?) # => true
|
49
|
+
# Ok(1).ok_and?(&:even?) # => false
|
50
|
+
# Err(:a).ok_and? { |_| true } # => false
|
51
|
+
# Err(:b).ok_and? { |_| false } # => false
|
52
|
+
def ok_and?(&block)
|
53
|
+
if ok?
|
54
|
+
!!block.call(value)
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return true if the inner value is an Err and the result of the block is
|
61
|
+
# truthy.
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# Ok(1).err_and?(&:odd?) # => false
|
65
|
+
# Ok(1).err_and?(&:even?) # => false
|
66
|
+
# Err(:a).err_and? { |_| true } # => true
|
67
|
+
# Err(:b).err_and? { |_| false } # => false
|
68
|
+
def err_and?(&block)
|
69
|
+
if err?
|
70
|
+
!!block.call(value)
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Return the inner value of an Ok, else raise an exception when Err.
|
77
|
+
#
|
78
|
+
# @example
|
79
|
+
# Ok(1).unwrap! # => 1
|
80
|
+
# Err(:c).unwrap! # => raise Errgonomic::UnwrapError, "value is an Err"
|
81
|
+
def unwrap!
|
82
|
+
raise Errgonomic::UnwrapError, 'value is an Err' unless ok?
|
83
|
+
|
84
|
+
@value
|
85
|
+
end
|
86
|
+
|
87
|
+
# Return the inner value of an Ok, else raise an exception with the given
|
88
|
+
# message when Err.
|
89
|
+
#
|
90
|
+
# @param msg [String]
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# Ok(1).expect!("should have worked") # => 1
|
94
|
+
# Err(:d).expect!("should have worked") # => raise Errgonomic::ExpectError, "should have worked"
|
95
|
+
def expect!(msg)
|
96
|
+
raise Errgonomic::ExpectError, msg unless ok?
|
97
|
+
|
98
|
+
@value
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return the inner value of an Err, else raise an exception when Ok.
|
102
|
+
#
|
103
|
+
# @example
|
104
|
+
# Ok(1).unwrap_err! # => raise Errgonomic::UnwrapError, 1
|
105
|
+
# Err(:e).unwrap_err! # => :e
|
106
|
+
def unwrap_err!
|
107
|
+
raise Errgonomic::UnwrapError, value unless err?
|
108
|
+
|
109
|
+
@value
|
110
|
+
end
|
111
|
+
|
112
|
+
# Given another result, return it if the inner result is Ok, else return
|
113
|
+
# the inner Err. Raise an exception if the other value is not a Result.
|
114
|
+
#
|
115
|
+
# @param other [Errgonomic::Result::Any]
|
116
|
+
#
|
117
|
+
# @example
|
118
|
+
# Ok(1).and(Ok(2)) # => Ok(2)
|
119
|
+
# Ok(1).and(Err(:f)) # => Err(:f)
|
120
|
+
# Err(:g).and(Ok(1)) # => Err(:g)
|
121
|
+
# Err(:h).and(Err(:i)) # => Err(:h)
|
122
|
+
# Ok(1).and(2) # => raise Errgonomic::ArgumentError, "other must be a Result"
|
123
|
+
def and(other)
|
124
|
+
raise Errgonomic::ArgumentError, 'other must be a Result' unless other.is_a?(Errgonomic::Result::Any)
|
125
|
+
return self if err?
|
126
|
+
|
127
|
+
other
|
128
|
+
end
|
129
|
+
|
130
|
+
# Given a block, evaluate it and return its result if the inner result is
|
131
|
+
# Ok, else return the inner Err. This is lazy evaluated, and we
|
132
|
+
# pedantically check the type of the block's return value at runtime. This
|
133
|
+
# is annoying, sorry, but better than an "undefined method" error.
|
134
|
+
# Hopefully it gives your test suite a chance to detect incorrect usage.
|
135
|
+
#
|
136
|
+
# @param block [Proc]
|
137
|
+
#
|
138
|
+
# @example
|
139
|
+
# Ok(1).and_then { |x| Ok(x + 1) } # => Ok(2)
|
140
|
+
# Ok(1).and_then { |_| Err(:error) } # => Err(:error)
|
141
|
+
# Err(:error).and_then { |x| Ok(x + 1) } # => Err(:error)
|
142
|
+
# Err(:error).and_then { |x| Err(:error2) } # => Err(:error)
|
143
|
+
def and_then(&block)
|
144
|
+
return self if err?
|
145
|
+
|
146
|
+
res = block.call(value)
|
147
|
+
if !res.is_a?(Errgonomic::Result::Any) && Errgonomic.give_me_ambiguous_downstream_errors?
|
148
|
+
raise Errgonomic::ArgumentError, 'and_then block must return a Result'
|
149
|
+
end
|
150
|
+
|
151
|
+
res
|
152
|
+
end
|
153
|
+
|
154
|
+
# Return other if self is Err, else return the original Option. Raises a
|
155
|
+
# pedantic runtime exception if other is not a Result.
|
156
|
+
#
|
157
|
+
# @param other [Errgonomic::Result::Any]
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# Err(:j).or(Ok(1)) # => Ok(1)
|
161
|
+
# Err(:k).or(Err(:l)) # => Err(:l)
|
162
|
+
# Err(:m).or("oops") # => raise Errgonomic::ArgumentError, "other must be a Result; you might want unwrap_or"
|
163
|
+
def or(other)
|
164
|
+
unless other.is_a?(Errgonomic::Result::Any)
|
165
|
+
raise Errgonomic::ArgumentError,
|
166
|
+
'other must be a Result; you might want unwrap_or'
|
167
|
+
end
|
168
|
+
return other if err?
|
169
|
+
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
# Return self if it is Ok, else lazy evaluate the block and return its
|
174
|
+
# result. Raises a pedantic runtime check that the block returns a Result.
|
175
|
+
# Sorry about that, hopefully it helps your tests. Better than ambiguous
|
176
|
+
# downstream "undefined method" errors, probably.
|
177
|
+
#
|
178
|
+
# @param block [Proc]
|
179
|
+
#
|
180
|
+
# @example
|
181
|
+
# Ok(1).or_else { Ok(2) } # => Ok(1)
|
182
|
+
# Err(:o).or_else { Ok(1) } # => Ok(1)
|
183
|
+
# Err(:q).or_else { Err(:r) } # => Err(:r)
|
184
|
+
# Err(:s).or_else { "oops" } # => raise Errgonomic::ArgumentError, "or_else block must return a Result"
|
185
|
+
def or_else(&block)
|
186
|
+
return self if ok?
|
187
|
+
|
188
|
+
res = block.call(self)
|
189
|
+
if !res.is_a?(Errgonomic::Result::Any) && Errgonomic.give_me_ambiguous_downstream_errors?
|
190
|
+
raise Errgonomic::ArgumentError, 'or_else block must return a Result'
|
191
|
+
end
|
192
|
+
|
193
|
+
res
|
194
|
+
end
|
195
|
+
|
196
|
+
# Return the inner value if self is Ok, else return the provided default.
|
197
|
+
#
|
198
|
+
# @param other [Object]
|
199
|
+
#
|
200
|
+
# @example
|
201
|
+
# Ok(1).unwrap_or(2) # => 1
|
202
|
+
# Err(:t).unwrap_or(:u) # => :u
|
203
|
+
def unwrap_or(other)
|
204
|
+
return value if ok?
|
205
|
+
|
206
|
+
other
|
207
|
+
end
|
208
|
+
|
209
|
+
# Return the inner value if self is Ok, else lazy evaluate the block and
|
210
|
+
# return its result.
|
211
|
+
#
|
212
|
+
# @param block [Proc]
|
213
|
+
#
|
214
|
+
# @example
|
215
|
+
# Ok(1).unwrap_or_else { 2 } # => 1
|
216
|
+
# Err(:v).unwrap_or_else { :w } # => :w
|
217
|
+
def unwrap_or_else(&block)
|
218
|
+
return value if ok?
|
219
|
+
|
220
|
+
block.call(self)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
# The Ok variant.
|
225
|
+
class Ok < Any
|
226
|
+
attr_accessor :value
|
227
|
+
|
228
|
+
# Ok is always ok
|
229
|
+
#
|
230
|
+
# @example
|
231
|
+
# Ok(1).ok? # => true
|
232
|
+
def ok?
|
233
|
+
true
|
234
|
+
end
|
235
|
+
|
236
|
+
# Ok is never err
|
237
|
+
#
|
238
|
+
# @example
|
239
|
+
# Ok(1).err? # => false
|
240
|
+
def err?
|
241
|
+
false
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
class Err < Any
|
246
|
+
class Arbitrary; end
|
247
|
+
|
248
|
+
attr_accessor :value
|
249
|
+
|
250
|
+
# Err may be constructed without a value, if you want.
|
251
|
+
#
|
252
|
+
# @example
|
253
|
+
# Err(:y).value # => :y
|
254
|
+
# Err().value # => Arbitrary
|
255
|
+
def initialize(value = Arbitrary)
|
256
|
+
super(value)
|
257
|
+
end
|
258
|
+
|
259
|
+
# Err is always err
|
260
|
+
#
|
261
|
+
# @example
|
262
|
+
# Err(:z).err? # => true
|
263
|
+
def err?
|
264
|
+
true
|
265
|
+
end
|
266
|
+
|
267
|
+
# Err is never ok
|
268
|
+
#
|
269
|
+
# @example
|
270
|
+
# Err(:A).ok? # => false
|
271
|
+
def ok?
|
272
|
+
false
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# Introduce certain helper methods into the Object class.
|
279
|
+
#
|
280
|
+
# @example
|
281
|
+
# "foo".result? # => false
|
282
|
+
# "foo".assert_result! # => raise Errgonomic::ResultRequiredError
|
283
|
+
class Object
|
284
|
+
# Convenience method to indicate whether we are working with a result.
|
285
|
+
# TBD whether we implement some stubs for the rest of the Result API; I want
|
286
|
+
# to think about how effectively these map to truthiness or presence.
|
287
|
+
#
|
288
|
+
# @example
|
289
|
+
# "foo".result? # => false
|
290
|
+
# Ok("foo").result? # => true
|
291
|
+
def result?
|
292
|
+
false
|
293
|
+
end
|
294
|
+
|
295
|
+
# Lacking static typing, we are going to want to make it easy to enforce at
|
296
|
+
# runtime that a given object is a Result.
|
297
|
+
#
|
298
|
+
# @example
|
299
|
+
# "foo".assert_result! # => raise Errgonomic::ResultRequiredError
|
300
|
+
# Ok("foo").assert_result! # => true
|
301
|
+
def assert_result!
|
302
|
+
return true if result?
|
303
|
+
|
304
|
+
raise Errgonomic::ResultRequiredError
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
# Global convenience method for constructing an Ok result.
|
309
|
+
def Ok(value)
|
310
|
+
Errgonomic::Result::Ok.new(value)
|
311
|
+
end
|
312
|
+
|
313
|
+
# Global convenience method for constructing an Err result.
|
314
|
+
def Err(value = Errgonomic::Result::Err::Arbitrary)
|
315
|
+
Errgonomic::Result::Err.new(value)
|
316
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# Returns the receiver if it matches the expected type, otherwise raises a TypeMismatchError.
|
5
|
+
# This is useful for enforcing type expectations in method arguments.
|
6
|
+
#
|
7
|
+
# @param type [Class] The expected type or module the receiver should be.
|
8
|
+
# @param message [String] Optional error message to raise if type doesn't match.
|
9
|
+
# @return [Object] The receiver if it is of the expected type.
|
10
|
+
# @example
|
11
|
+
# 'hello'.type_or_raise!(String) #=> "hello"
|
12
|
+
# 123.type_or_raise!(String, "We need a string!") #=> raise Errgonomic::TypeMismatchError, "We need a string!"
|
13
|
+
# 123.type_or_raise!(String) #=> raise Errgonomic::TypeMismatchError, "Expected String but got Integer"
|
14
|
+
def type_or_raise!(type, message = nil)
|
15
|
+
message ||= "Expected #{type} but got #{self.class}"
|
16
|
+
raise Errgonomic::TypeMismatchError, message unless is_a?(type)
|
17
|
+
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
alias type_or_raise type_or_raise!
|
22
|
+
|
23
|
+
# Returns the receiver if it matches the expected type, otherwise returns the default value.
|
24
|
+
#
|
25
|
+
# @param type [Class] The expected type or module the receiver should be.
|
26
|
+
# @param default [Object] The value to return if type doesn't match.
|
27
|
+
# @return [Object] The receiver if it is of the expected type, otherwise the default value.
|
28
|
+
# @example
|
29
|
+
# 'hello'.type_or(String, 'default') # => "hello"
|
30
|
+
# 123.type_or(String, 'default') # => "default"
|
31
|
+
def type_or(type, default)
|
32
|
+
return self if is_a?(type)
|
33
|
+
|
34
|
+
default
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the receiver if it matches the expected type, otherwise returns the result of the block.
|
38
|
+
# Useful when constructing the default value is expensive.
|
39
|
+
#
|
40
|
+
# @param type [Class] The expected type or module the receiver should be.
|
41
|
+
# @param block [Proc] The block to call if type doesn't match.
|
42
|
+
# @return [Object] The receiver if it is of the expected type, otherwise the block result.
|
43
|
+
# @example
|
44
|
+
# 'hello'.type_or_else(String) { 'default' } # => "hello"
|
45
|
+
# 123.type_or_else(String) { 'default' } # => "default"
|
46
|
+
def type_or_else(type, &block)
|
47
|
+
return self if is_a?(type)
|
48
|
+
|
49
|
+
block.call
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the receiver if it does not match the expected type, otherwise raises a TypeMismatchError.
|
53
|
+
#
|
54
|
+
# @param type [Class] The type or module the receiver should not be.
|
55
|
+
# @param message [String] Optional error message to raise if type matches.
|
56
|
+
# @return [Object] The receiver if it is not of the specified type.
|
57
|
+
# @example
|
58
|
+
# 'hello'.not_type_or_raise!(Integer) #=> "hello"
|
59
|
+
# 123.not_type_or_raise!(Integer, "We dont want an integer!") #=> raise Errgonomic::TypeMismatchError, "We dont want an integer!"
|
60
|
+
# 123.not_type_or_raise!(Integer) #=> raise Errgonomic::TypeMismatchError, "Expected anything but Integer but got Integer"
|
61
|
+
def not_type_or_raise!(type, message = nil)
|
62
|
+
message ||= "Expected anything but #{type} but got #{self.class}"
|
63
|
+
raise Errgonomic::TypeMismatchError, message if is_a?(type)
|
64
|
+
|
65
|
+
self
|
66
|
+
end
|
67
|
+
end
|
data/lib/errgonomic/version.rb
CHANGED
data/lib/errgonomic.rb
CHANGED
@@ -1,59 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'errgonomic/version' unless defined?(Errgonomic::VERSION)
|
4
4
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
# A more opinionated blend with Rails presence.
|
6
|
+
require_relative 'errgonomic/presence'
|
7
|
+
|
8
|
+
# Bring in a subtle and manual type checker.
|
9
|
+
require_relative 'errgonomic/type'
|
10
|
+
|
11
|
+
# Bring in our Option and Result.
|
12
|
+
require_relative 'errgonomic/option'
|
13
|
+
require_relative 'errgonomic/result'
|
11
14
|
|
15
|
+
# Errgonomic adds opinionated abstractions to handle errors in a way that blends
|
16
|
+
# Rust and Ruby ergonomics. This library leans on Rails conventions for some
|
17
|
+
# presence-related methods; when in doubt, make those feel like Rails. It also
|
18
|
+
# has an implementation of Option and Result; when in doubt, make those feel
|
19
|
+
# more like Rust.
|
12
20
|
module Errgonomic
|
13
21
|
class Error < StandardError; end
|
14
22
|
|
15
23
|
class NotPresentError < Error; end
|
16
24
|
|
17
25
|
class TypeMismatchError < Error; end
|
18
|
-
end
|
19
26
|
|
20
|
-
class
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
class UnwrapError < Error; end
|
28
|
+
|
29
|
+
class ExpectError < Error; end
|
30
|
+
|
31
|
+
class ArgumentError < Error; end
|
32
|
+
|
33
|
+
class ResultRequiredError < Error; end
|
34
|
+
|
35
|
+
class NotComparableError < StandardError; end
|
36
|
+
|
37
|
+
# A little bit of control over how pedantic we are in our runtime type checks.
|
38
|
+
def self.give_me_ambiguous_downstream_errors?
|
39
|
+
@give_me_ambiguous_downstream_errors || true
|
40
|
+
end
|
41
|
+
|
42
|
+
# You can opt out of the pedantic runtime checks for lazy block evaluation,
|
43
|
+
# but not quietly.
|
44
|
+
def self.with_ambiguous_downstream_errors
|
45
|
+
original_value = @give_me_ambiguous_downstream_errors
|
46
|
+
@give_me_ambiguous_downstream_errors = true
|
47
|
+
yield
|
48
|
+
ensure
|
49
|
+
@give_me_ambiguous_downstream_errors = original_value
|
30
50
|
end
|
31
51
|
|
32
|
-
#
|
33
|
-
#
|
34
|
-
|
35
|
-
|
36
|
-
# @param value [Object] The value to return if the receiver is not present.
|
37
|
-
# @return [Object] The receiver if it is present, otherwise the given value.
|
38
|
-
def present_or(value)
|
39
|
-
# TBD whether this is *too* strict
|
40
|
-
if value.class != self.class && self.class != NilClass
|
41
|
-
raise Errgonomic::TypeMismatchError, "Type mismatch: default value is a #{value.class} but original was a #{self.class}"
|
42
|
-
end
|
43
|
-
|
44
|
-
return self if present?
|
45
|
-
|
46
|
-
value
|
52
|
+
# Lenient inner value comparison means the inner value of a Some or Ok can be
|
53
|
+
# compared to some other non-Result or non-Option value.
|
54
|
+
def self.lenient_inner_value_comparison?
|
55
|
+
@lenient_inner_value_comparison ||= true
|
47
56
|
end
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
# +present_or+, if constructing the default value is expensive.
|
52
|
-
#
|
53
|
-
# @param block [Proc] The block to call if the receiver is not present.
|
54
|
-
# @return [Object] The receiver if it is present, otherwise the result of the block.
|
55
|
-
def present_or_else(&block)
|
56
|
-
return block.call if blank?
|
57
|
-
self
|
58
|
+
def self.give_me_lenient_inner_value_comparison=(value)
|
59
|
+
@lenient_inner_value_comparison = value
|
58
60
|
end
|
59
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: errgonomic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Zadrozny
|
@@ -24,6 +24,34 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: yard
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.9'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.9'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: yard-doctest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.1'
|
27
55
|
description: Let's blend the Rails 'present' and 'blank' conventions with a few patterns
|
28
56
|
from Rust Option types.
|
29
57
|
email:
|
@@ -34,17 +62,24 @@ extra_rdoc_files: []
|
|
34
62
|
files:
|
35
63
|
- ".envrc"
|
36
64
|
- ".rspec"
|
65
|
+
- ".rubocop.yml"
|
37
66
|
- ".standard.yml"
|
67
|
+
- ".yardopts"
|
38
68
|
- CHANGELOG.md
|
39
69
|
- CODE_OF_CONDUCT.md
|
40
70
|
- LICENSE.txt
|
41
71
|
- README.md
|
42
72
|
- Rakefile
|
73
|
+
- doctest_helper.rb
|
43
74
|
- flake.lock
|
44
75
|
- flake.nix
|
45
76
|
- gemset.nix
|
46
77
|
- lib/errgonomic.rb
|
47
78
|
- lib/errgonomic/core_ext/blank.rb
|
79
|
+
- lib/errgonomic/option.rb
|
80
|
+
- lib/errgonomic/presence.rb
|
81
|
+
- lib/errgonomic/result.rb
|
82
|
+
- lib/errgonomic/type.rb
|
48
83
|
- lib/errgonomic/version.rb
|
49
84
|
- sig/errgonomic.rbs
|
50
85
|
homepage: https://omc.io/
|