resulting 0.0.1 → 0.1.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/.projections.json +4 -0
- data/.rspec +1 -1
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +3 -0
- data/README.md +308 -7
- data/TODO.md +3 -0
- data/lib/resulting.rb +25 -2
- data/lib/resulting/handler.rb +17 -0
- data/lib/resulting/helpers.rb +17 -0
- data/lib/resulting/result.rb +5 -0
- data/lib/resulting/resultable.rb +45 -0
- data/lib/resulting/runner.rb +28 -0
- data/lib/resulting/version.rb +1 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a335ef962f6b9785f66c8c4d6830f575ba5db1910d3d49e74e693c83798775a0
|
4
|
+
data.tar.gz: fd89e762a7bc39aec9be3678478509c6306482aa4ca81f8954a07c9c61e0e06f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2212406ba4ac45959186a25b579d20cfac6bf7b784abe62d81d184daac9ee42a866af16d4a32f87981ae48bcadf7288e21b409482bd3fbdd6c1369f6d2cee8e
|
7
|
+
data.tar.gz: 919091b0a3a3c486871815aa105a7714238ba4e16959cc55e272460763a4d222e3d87db412f752bb0a7e8a5ea174b4c25c73e75c5270d5b343e8e9af9d853f7d
|
data/.projections.json
ADDED
data/.rspec
CHANGED
data/.rubocop.yml
CHANGED
@@ -16,7 +16,7 @@ Layout/MultilineMethodCallIndentation:
|
|
16
16
|
Enabled: false
|
17
17
|
|
18
18
|
Layout/LineLength:
|
19
|
-
Max:
|
19
|
+
Max: 110
|
20
20
|
Exclude:
|
21
21
|
- Rakefile
|
22
22
|
|
@@ -53,6 +53,9 @@ RSpec/MessageSpies:
|
|
53
53
|
RSpec/MultipleExpectations:
|
54
54
|
Enabled: false
|
55
55
|
|
56
|
+
RSpec/NestedGroups:
|
57
|
+
Max: 4
|
58
|
+
|
56
59
|
RSpec/NotToNot:
|
57
60
|
EnforcedStyle: to_not
|
58
61
|
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
# Resulting
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
`lib/resulting`. To experiment with that code, run `bin/console` for an interactive prompt.
|
6
|
-
|
7
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
Resulting is a gem to help with result handling and coordinating validations and
|
4
|
+
saving of (primarily) ActiveRecord objects.
|
8
5
|
|
9
6
|
## Installation
|
10
7
|
|
@@ -24,7 +21,311 @@ Or install it yourself as:
|
|
24
21
|
|
25
22
|
## Usage
|
26
23
|
|
27
|
-
|
24
|
+
There is a common pattern in a rails controller doing something like this:
|
25
|
+
|
26
|
+
- Controller action calls a service (or two or three)
|
27
|
+
- That service returns an object (or two or three)
|
28
|
+
- If you want to see if it was successful, that service may have its own result
|
29
|
+
object, or you can check if the object was persisted.
|
30
|
+
- Maybe the service does that and just returns and object for serialization
|
31
|
+
(more likely since we should have skinny controllers). But then you have the
|
32
|
+
same problem.
|
33
|
+
- Result objects are hard to manage outside a framework explicitly and
|
34
|
+
ruthlessly designed to use them.
|
35
|
+
|
36
|
+
There are of course some very complicated situations, but many situations can be
|
37
|
+
solved using `Resulting`.
|
38
|
+
|
39
|
+
While `Resulting` can be used in any way you see fit, the way I use it is
|
40
|
+
described below.
|
41
|
+
|
42
|
+
### Custom Results
|
43
|
+
|
44
|
+
First we create a result object specific to our controller action. The reason
|
45
|
+
for this is we don't need a result object that is so flexible it is basically an
|
46
|
+
openstruct, but we want something with a slightly nicer API than a hash.
|
47
|
+
|
48
|
+
Additionally, this adds clarity, with a tested class, to the result object. So
|
49
|
+
anyone looking for what this result contains knows to just look for a result
|
50
|
+
named after the controller action.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
class CreateUserAndWidgetResult
|
54
|
+
include Resulting::Resultable
|
55
|
+
|
56
|
+
def user
|
57
|
+
value[:user]
|
58
|
+
end
|
59
|
+
|
60
|
+
def widget
|
61
|
+
value[:widget]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
```
|
65
|
+
|
66
|
+
### Controller
|
67
|
+
|
68
|
+
Now in our controller, since we know the result looks like, we can simply grab
|
69
|
+
the relevant objects out of it and set them to instance variables for a view, or
|
70
|
+
put them into JSON with [JBuilder](https://github.com/rails/jbuilder) or whatever.
|
71
|
+
|
72
|
+
We can also just check to see if our result was successful, the simplest API for
|
73
|
+
a result object.
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
class NewController
|
77
|
+
def create
|
78
|
+
result = UserAndWidgetCreateService.call(params)
|
79
|
+
@user = result.user
|
80
|
+
@widget = result.widget
|
81
|
+
|
82
|
+
if result.success?
|
83
|
+
redirect_to :show
|
84
|
+
else
|
85
|
+
render :new
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
### Result Object and Handlers
|
92
|
+
|
93
|
+
Finally, in our service, we initialize the result object we first defined with
|
94
|
+
our objects that we need to validate, save, and do whatever on.
|
95
|
+
|
96
|
+
Then we call the shortcut `.validate_and_save` method which will validate all
|
97
|
+
objects, this ensures that all objects will have `errors` even if the first one
|
98
|
+
fails validation.
|
99
|
+
|
100
|
+
If they are all valid, it will call `.save` (not `save!`) on each of them, inside an
|
101
|
+
`ActiveRecord::Base.transaction`. If all `.save` calls return `true`. Then we
|
102
|
+
will return a succesful result. If any of them return `false`, we will bail out
|
103
|
+
early and raise an `ActiveRecord::Rollback` error inside of the transaction.
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
class UserAndWidgetCreateService
|
107
|
+
def call(params)
|
108
|
+
new_result = CreateResult.success({
|
109
|
+
user: User.build(params[:user])
|
110
|
+
widget: Widget.build(params[:widget])
|
111
|
+
role: Role.build(user: user, widget: widget, role: :admin)
|
112
|
+
})
|
113
|
+
|
114
|
+
Resulting.validate_and_save(result)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
## Details
|
120
|
+
|
121
|
+
1. [`Resulting::Runner`](#resultingrunner)
|
122
|
+
1. [`.run_all`](#run_allresult-method)
|
123
|
+
1. [`.run_until_failure`](#run_until_failureresult-method)
|
124
|
+
1. [With blocks](#with-blocks)
|
125
|
+
1. [Options (`:failure_case`, `:wrapper`)](#options-failure_case-wrapper)
|
126
|
+
1. [With Rails](#with-rails)
|
127
|
+
1. [`Resulting::Handler`](#resultinghandler)
|
128
|
+
1. [`Resulting::Result`](#resultingresult)
|
129
|
+
1. [Constructors (`.new`, `.success`, and `.failure`](#constructors-new-success-failure)
|
130
|
+
1. [`.wrap`](#wrap)
|
131
|
+
1. [Methods (`#value`, `#success?`, and `#failure?`](#methods-value-success-and-failure)
|
132
|
+
1. [Values](#values)
|
133
|
+
1. [Resulting::Helpers](#resultinghelpers)
|
134
|
+
|
135
|
+
## Resulting::Runner
|
136
|
+
|
137
|
+
The `Resulting::Runner`'s will take a result object, and if that result is
|
138
|
+
failing, return immediately. That way you can safely pass the results to any
|
139
|
+
method that takes them without worrying about acting on a failed result. (It's
|
140
|
+
almost like a monad, but definitely not a monad).
|
141
|
+
|
142
|
+
### `.run_all(result, method:)`
|
143
|
+
|
144
|
+
This will call the given `method` on every object in `result.values`. It will
|
145
|
+
keep track whether or not all calls to `method` on each object were true.
|
146
|
+
|
147
|
+
If all calls to `method` were `true`, it will return a successful result.
|
148
|
+
|
149
|
+
### `.run_until_failure(result, method:)`
|
150
|
+
|
151
|
+
This will call the given `method` on every object in `result.values` UNTIL it
|
152
|
+
sees a failure. At that point, it will bail out and stop calling the method.
|
153
|
+
|
154
|
+
### With Blocks
|
155
|
+
|
156
|
+
Both of these methods take an optional block:
|
157
|
+
|
158
|
+
- In `run_all`, the block will be run no matter what. The return value of the
|
159
|
+
block will be `&&`'d with the current success value of calling `method` on all
|
160
|
+
the values. That new success value will determine whether the call was
|
161
|
+
successful.
|
162
|
+
```ruby
|
163
|
+
Resulting::Runner.run_all(result, method: :validate) do
|
164
|
+
# Validate other things
|
165
|
+
# return true
|
166
|
+
end
|
167
|
+
```
|
168
|
+
- In `run_until_falure`, the block will be run no matter what. The return value of the
|
169
|
+
block will be `&&`'d with the current success value of calling `method` on all
|
170
|
+
the values. That new success value will determine whether the call was
|
171
|
+
successful.
|
172
|
+
```ruby
|
173
|
+
Resulting::Runner.run_until_failure(result, method: :validate) do
|
174
|
+
# Save other things
|
175
|
+
# return true
|
176
|
+
end
|
177
|
+
```
|
178
|
+
|
179
|
+
****NOTE: The return value of the block is what is used to determine
|
180
|
+
success.**** Be mindful of the return value.
|
181
|
+
|
182
|
+
### Options (`:failure_case`, `:wrapper`)
|
183
|
+
|
184
|
+
`failure_case` is an optional argument. It should be a lambda that describes
|
185
|
+
what to do at the end if a failure is encountered. By default it's just a lambda
|
186
|
+
that returns false.
|
187
|
+
|
188
|
+
For example, when validating, if all `:validate` calls have returned false, we
|
189
|
+
just want to return `false`. However, if we are saving, and one of the saves
|
190
|
+
returns false, we actually want to do `raise ActiveRecord::Rollback`.
|
191
|
+
|
192
|
+
Odds are you will either return false or raise some error, but any lambda will
|
193
|
+
do.
|
194
|
+
|
195
|
+
`wrapper` is something that will wrap the whole result handling process. The
|
196
|
+
common example here would be to wrap all saves in an
|
197
|
+
`ActiveRecord::Base.transaction` block to ensure we can rollback safely.
|
198
|
+
|
199
|
+
### With Rails (`.validate`, `.save`, and `.validate_and_save`)
|
200
|
+
|
201
|
+
Most of the time this is used within rails, and as described there are some
|
202
|
+
things you will commonly want to do.
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
Resulting.validate(param)
|
206
|
+
```
|
207
|
+
|
208
|
+
Is equivalent to:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
Resulting::Runner.run_all(param, method: :validate)
|
212
|
+
```
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
Resulting.save(param)
|
216
|
+
```
|
217
|
+
|
218
|
+
Is equivalent to:
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
Resulting::Runner.run_until_failure(
|
222
|
+
param,
|
223
|
+
method: :save,
|
224
|
+
failure_case: -> { raise ActiveRecord::Rollback },
|
225
|
+
wrapper: -> { ActiveRecord::Base.method(:transaction) },
|
226
|
+
)
|
227
|
+
```
|
228
|
+
|
229
|
+
Both of these still take blocks.
|
230
|
+
|
231
|
+
Finally, `Resulting.validate_and_save` will just call one after the other. This
|
232
|
+
one does not take a block, so it assumes you just want to validating everything
|
233
|
+
and then save it.
|
234
|
+
|
235
|
+
## Resulting::Result
|
236
|
+
|
237
|
+
This is a generic result class that implements `Resulting::Resultable`.
|
238
|
+
|
239
|
+
### Constructors: (`.new`, `.success`, `.failure`)
|
240
|
+
|
241
|
+
- `.new(success, value)` stores the value and sets success to the first
|
242
|
+
parameter
|
243
|
+
- `.success(value)` stores the value and sets success to true
|
244
|
+
- `.failure(value)` stores the value and sets success as false
|
245
|
+
|
246
|
+
### `.wrap`
|
247
|
+
|
248
|
+
`Resulting::Result.wrap` is worth calling out on its own. `Result.wrap(value)`
|
249
|
+
will do the following:
|
250
|
+
|
251
|
+
- If `value` is a result (i.e. implements `Resulting::Resultable`) it returns
|
252
|
+
the value.
|
253
|
+
- If `value` is anything else, it will return `Result.success(value)`.
|
254
|
+
|
255
|
+
```ruby
|
256
|
+
$ foo = Object.new
|
257
|
+
$ result = Resulting::Result.wrap(foo)
|
258
|
+
$ result
|
259
|
+
=> #<Resulting::Result:0x00007f91dd072238 @success=true, @value=#<Object:0x00007f91db929950>>
|
260
|
+
$ Resulting::Result.wrap(result)
|
261
|
+
=> #<Resulting::Result:0x00007f91dd072238 @success=true, @value=#<Object:0x00007f91db929950>>
|
262
|
+
```
|
263
|
+
|
264
|
+
You can use wrap to ensure you have a result object if you need it.
|
265
|
+
|
266
|
+
### Methods: `#value`, `#success?`, and `#failure?`
|
267
|
+
|
268
|
+
A result has helper methods, `#success?` and `#failure?` which just check whether
|
269
|
+
`success` is truthy, and the obj is stored as the `value`.
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
success = obj.validate # => true
|
273
|
+
result = Resulting::Result.new(success, obj)
|
274
|
+
|
275
|
+
result.success? # => true
|
276
|
+
result.value # => obj
|
277
|
+
```
|
278
|
+
|
279
|
+
### `#values`
|
280
|
+
|
281
|
+
`values` returns the `value` collapsed into an array. This variable is iterated
|
282
|
+
over by the two runner methods.
|
283
|
+
|
284
|
+
****NOTE: Resulting assumes any methods calls on the value mutate the value
|
285
|
+
itself and that it is passed by reference.****
|
286
|
+
|
287
|
+
- If `value` is a `Hash`, `values` is `value.values.flatten`
|
288
|
+
- If `value` is anything else, `values` is `Array(value).flatten`
|
289
|
+
- (This will wrap objects in an array, and leave arrays alone.)
|
290
|
+
|
291
|
+
When building your own result you can override this to provide different
|
292
|
+
behavior. You could use this maintain access to an object but not call a method
|
293
|
+
on it, or to add data you want acted on from a side effect.
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
class MyResult
|
297
|
+
def user
|
298
|
+
values[:user]
|
299
|
+
end
|
300
|
+
|
301
|
+
def hashed_password
|
302
|
+
values[:password] # Omit from values, so it's not acted on
|
303
|
+
end
|
304
|
+
|
305
|
+
def values
|
306
|
+
[user, user.side_effect_record]
|
307
|
+
end
|
308
|
+
end
|
309
|
+
```
|
310
|
+
|
311
|
+
In this case, we have a password (or any object in memory we don't/can't
|
312
|
+
persist). It will be on the result object so we can do something with it, but by
|
313
|
+
omitting it from `#values`, we don't have to worry about it being acted on.
|
314
|
+
|
315
|
+
In contrast, let's say in our services we create some record as a side effect
|
316
|
+
which couldn't be created at the time we created the result (this is pretty
|
317
|
+
contrived, but go with it), then we can add that to the values as something to
|
318
|
+
be validated, saved, or whatever when the runners process the result.
|
319
|
+
|
320
|
+
## Resulting::Helpers
|
321
|
+
|
322
|
+
If you include `Resulting::Helpers` in a given class or module, you get the
|
323
|
+
some nifty helper shortcuts.
|
324
|
+
|
325
|
+
```ruby
|
326
|
+
Success(value) # Equal to Resulting::Result.success(value)
|
327
|
+
Failure(value) # Equal to Resulting::Result.failure(value)
|
328
|
+
```
|
28
329
|
|
29
330
|
## Development
|
30
331
|
|
@@ -35,4 +336,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
35
336
|
## Contributing
|
36
337
|
|
37
338
|
Bug reports and pull requests are welcome on GitHub at
|
38
|
-
https://github.com/
|
339
|
+
https://github.com/dewyze/resulting.
|
data/TODO.md
ADDED
data/lib/resulting.rb
CHANGED
@@ -1,6 +1,29 @@
|
|
1
1
|
require "resulting/version"
|
2
|
+
require "resulting/resultable"
|
3
|
+
require "resulting/helpers"
|
4
|
+
require "resulting/handler"
|
5
|
+
require "resulting/result"
|
6
|
+
require "resulting/runner"
|
2
7
|
|
3
8
|
module Resulting
|
4
|
-
class
|
5
|
-
|
9
|
+
class << self
|
10
|
+
def validate(result_or_value, &blk)
|
11
|
+
Resulting::Runner.run_all(result_or_value, method: :validate, &blk)
|
12
|
+
end
|
13
|
+
|
14
|
+
def save(result_or_value, &blk)
|
15
|
+
params = { method: :save }
|
16
|
+
|
17
|
+
if defined?(ActiveRecord::Base) && defined?(ActiveRecord::Rollback)
|
18
|
+
params[:failure_case] = -> { raise ActiveRecord::Rollback }
|
19
|
+
params[:wrapper] = ActiveRecord::Base.method(:transaction)
|
20
|
+
end
|
21
|
+
|
22
|
+
Resulting::Runner.run_until_failure(result_or_value, params, &blk)
|
23
|
+
end
|
24
|
+
|
25
|
+
def validate_and_save(result_or_value)
|
26
|
+
save(validate(result_or_value))
|
27
|
+
end
|
28
|
+
end
|
6
29
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Resulting
|
2
|
+
module Handler
|
3
|
+
include Resulting::Helpers
|
4
|
+
|
5
|
+
def self.handle(result_or_value, wrapper: ->(&blk) { return blk.call })
|
6
|
+
wrapper.call do
|
7
|
+
result = Resulting::Result.wrap(result_or_value)
|
8
|
+
|
9
|
+
return result if result.failure?
|
10
|
+
|
11
|
+
success = yield
|
12
|
+
|
13
|
+
result.class.new(success, result.value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Resulting
|
2
|
+
module Helpers
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def Success(*args, &block) # rubocop:disable Naming/MethodName
|
9
|
+
Resulting::Result.success(*args, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def Failure(*args, &block) # rubocop:disable Naming/MethodName
|
13
|
+
Resulting::Result.failure(*args, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Resulting
|
2
|
+
module Resultable
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
attr_reader :success, :value
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(success, value)
|
9
|
+
@success = success
|
10
|
+
@value = value.is_a?(Resulting::Resultable) ? value.value : value
|
11
|
+
end
|
12
|
+
|
13
|
+
def success?
|
14
|
+
@success
|
15
|
+
end
|
16
|
+
|
17
|
+
def failure?
|
18
|
+
!@success
|
19
|
+
end
|
20
|
+
|
21
|
+
def values
|
22
|
+
if value.is_a?(Hash)
|
23
|
+
value.values.flatten
|
24
|
+
else
|
25
|
+
Array(value).flatten
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
def success(value)
|
31
|
+
new(true, value)
|
32
|
+
end
|
33
|
+
|
34
|
+
def failure(value)
|
35
|
+
new(false, value)
|
36
|
+
end
|
37
|
+
|
38
|
+
def wrap(param)
|
39
|
+
return param if param.is_a?(Resulting::Resultable)
|
40
|
+
|
41
|
+
success(param)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Resulting
|
2
|
+
module Runner
|
3
|
+
def self.run_all(result, method:, failure_case: -> { false }, wrapper: ->(&blk) { blk.call })
|
4
|
+
Resulting::Handler.handle(result, wrapper: wrapper) do
|
5
|
+
new_result = result.values.reduce(true) do |success, v|
|
6
|
+
v.send(method) ? success : false
|
7
|
+
end
|
8
|
+
|
9
|
+
if block_given?
|
10
|
+
block_result = yield
|
11
|
+
new_result &&= block_result
|
12
|
+
end
|
13
|
+
|
14
|
+
new_result ? true : failure_case.call
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.run_until_failure(result, method:, failure_case: -> { false }, wrapper: ->(&blk) { blk.call })
|
19
|
+
Resulting::Handler.handle(result, wrapper: wrapper) do
|
20
|
+
result = result.values.all?(&method)
|
21
|
+
|
22
|
+
result &&= yield if block_given?
|
23
|
+
|
24
|
+
result ? true : failure_case.call
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/resulting/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resulting
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John DeWyze
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-04-
|
11
|
+
date: 2020-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry-byebug
|
@@ -93,6 +93,7 @@ extensions: []
|
|
93
93
|
extra_rdoc_files: []
|
94
94
|
files:
|
95
95
|
- ".gitignore"
|
96
|
+
- ".projections.json"
|
96
97
|
- ".rspec"
|
97
98
|
- ".rubocop.yml"
|
98
99
|
- ".travis.yml"
|
@@ -102,11 +103,17 @@ files:
|
|
102
103
|
- LICENSE
|
103
104
|
- README.md
|
104
105
|
- Rakefile
|
106
|
+
- TODO.md
|
105
107
|
- bin/console
|
106
108
|
- bin/rake
|
107
109
|
- bin/rubocop
|
108
110
|
- bin/setup
|
109
111
|
- lib/resulting.rb
|
112
|
+
- lib/resulting/handler.rb
|
113
|
+
- lib/resulting/helpers.rb
|
114
|
+
- lib/resulting/result.rb
|
115
|
+
- lib/resulting/resultable.rb
|
116
|
+
- lib/resulting/runner.rb
|
110
117
|
- lib/resulting/version.rb
|
111
118
|
- resulting.gemspec
|
112
119
|
homepage: https://github.com/dewyze/resulting
|