resonad 1.2.0 → 1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7eee55274773363f0220a61e2d4714d11a129869
4
- data.tar.gz: 05873de655e1cc85fe147e7b247788ad273f10d9
2
+ SHA256:
3
+ metadata.gz: 2751182e01f6cf2c97cdc99d46cb716ec1e517d52680bc75c92fd0f5c1bd693f
4
+ data.tar.gz: 2d1a5a21e81f7da804fa099d16a8b3a2032472e6f89112e4284942d050087293
5
5
  SHA512:
6
- metadata.gz: 34f5b90502c5737493195d5e44ed8b6686f1c9cb3145c240c09609db89deb5e577196e01ba55e3bdf3a9511d4107f996d8a26bbbcc7c4e55fc01f645956e312b
7
- data.tar.gz: a1a80de205c720d7f2ba54e799b97ad7cb0da4edac82b5dfba6aba8ab4b1fa87d7133fc03f71d452b4c834cf9c399ee85f076696290bcccbc6e81e3ac9cda482
6
+ metadata.gz: 6571a2f2e4e2ae98dee8c40efbf0bccf0aed09b6bc18cce47a5fb3fc83cc77c32141b31807d9b64b2842c62dfc737025ac24234dc22a1285f0e9910dae97cced
7
+ data.tar.gz: a000acabecf552daebeff7f10b1e57ab44f7fba224e8e85deb25acb7904b0c97981453931f008b68547b2fdade0e3ebec8d8b868af6757f4271a4a434f075cdb
data/.rspec CHANGED
@@ -1,2 +1,6 @@
1
+ --require spec_helper
2
+ <% if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7') %>
3
+ --exclude-pattern spec/pattern_matching_spec.rb
4
+ <% end %>
1
5
  --format documentation
2
6
  --color
@@ -0,0 +1 @@
1
+ 2.7
@@ -1,13 +1,25 @@
1
1
  language: ruby
2
+ script: bundle exec rspec
3
+
4
+ # test old rubies
2
5
  rvm:
3
- - 2.2.7
4
- - 2.3.4
5
- - 2.4.1
6
- cache: bundler
6
+ - 2.2.10
7
+ - 2.3.8
8
+ - 2.4.10
9
+ - 2.5.8
10
+ - 2.6.6
11
+
12
+ # test on latest ruby
13
+ matrix:
14
+ include:
15
+ - rvm: 2.7.1
16
+ env: LATEST_RUBY=true
17
+
18
+ # Rubygems deployment
7
19
  deploy:
8
20
  provider: rubygems
9
21
  on:
10
22
  tags: true
11
- rvm: 2.4.1
23
+ condition: $LATEST_RUBY = true
12
24
  api_key:
13
25
  secure: 0+R2SaUaKOZE0U4FwHiC/0DLepizJ1anjfvFEWk5pYVkaZl6HuaSYq50g8ff4VqXBH955Y5W7tFI8gfg4ZY9jrivHyEZT9Yoz3PFFPxcqSdVbDsV12RQt7ZjzW0HbvUhFu9nlrVACfFsLt4WFG61pyhXvewghp1p4JBp2UxeTk1kyL7U+wfWsp1RpcKiHkaLBeWJ0N87j4QkhTfcWlModLqN/19ATigvfyDjrwerkTescVmQi4TzfAiwkeAiDgUB32FkwJjbX9RfIko33CsuctuDRU/HT+RWiXcGAxdHZx4dtQpP9pAiNTVxXdIq+QAvitekIah70pdCTNKrOh3tDj3kglkUK23MqU6kdeXjmUn9r4SuzHCX0sVf16UpfnwuryDDPlG1ISY+mf7BARr/wNQWuAD4MA4kWiPGMqT/0uoysbY7dt44lkO9NV7HBbqs2shqqMtmgPgDoJ+SGTXo8LvrjuL0jHB2/MoHziiqWDKLQ9PS2Fcqp/06d5u8GcSRt7dcgo2rvwnMwRdUW6iCV0zQgzrNccWn/SsJROtgzEIkuLJYO0GIOCgNBJ0euorWqQBEEPniltwh5StSgH2bL5khdPxiI+LhsL7UDhWGiNFl5tlQp8Ob98WmmQ39ZyVAGKlJoe2rdE/IaDVfysVvQV5XzYUVRn4ZKftwubo5Zvw=
@@ -0,0 +1,50 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [1.3.0] - 2020-07-12
8
+ ### Added
9
+ - more documentation
10
+ - support for Ruby 2.7 pattern matching
11
+ - `#otherwise` alias for `#or_else`
12
+ - `#map_value` alias for `#map`
13
+ - alternate constructor methods
14
+ - aliases for `#on_success` and `#on_failure`
15
+ - `Success` and `Failure` class constants to `Resonad::Mixin`
16
+ - `Resonad::PublicMixin` for people who want the previous behaviour of
17
+ `Resonad::Mixin`
18
+ ### Changed
19
+ - The methods provided by `Resonad::Mixin` are now private. Replace with
20
+ `Resonad::PublicMixin` to revert them back to being public.
21
+
22
+ ## [1.2.0] - 2017-05-22
23
+ ### Added
24
+ - `Resonad.Success()` and `Resonad.Failure()` arguments are optional, and
25
+ default to nil.
26
+ - `#successful?` and `#ok?` as new aliases for `#success?`
27
+ - `#failed?` and `#bad?` as new aliases for `#failure?`
28
+
29
+ ## [1.1.1] - 2017-05-09
30
+ ### Fixed
31
+ - Aliased methods `#and_then` and `#or_else` were not aliased properly.
32
+
33
+ ## [1.1.0] - 2017-05-01
34
+ ### Added
35
+ - `Resonad::Mixin`
36
+ ### Changed
37
+ - `Resonad` is now a class. `Resonad::Success` and `Resonad::Failure` now
38
+ inherit from `Resonad`.
39
+
40
+ ## [1.0.2] - 2017-04-22
41
+ ### Fixed
42
+ - Typo in class names
43
+
44
+ ## [1.0.1] - 2017-04-22
45
+ ### Changed
46
+ - Nothing (bumped to force a deploy)
47
+
48
+ ## [1.0.0] - 2017-04-22
49
+ ### Added
50
+ - Everything (initial release)
data/README.md CHANGED
@@ -1,15 +1,26 @@
1
+ [![Build Status](https://travis-ci.org/tomdalling/resonad.svg?branch=master)](https://travis-ci.org/tomdalling/resonad)
2
+
1
3
  # Resonad
2
4
 
3
- Usage example (assume each method returns a `Resonad`):
5
+ Lightweight, functional "result" objects that can be used instead of exceptions.
6
+
7
+ Read: [Result Objects - Errors Without Exceptions](https://www.rubypigeon.com/posts/result-objects-errors-without-exceptions/)
8
+
9
+ ## Typical Usage Example
10
+
11
+ Assuming each method returns a `Resonad` (Ruby 2.7 syntax):
4
12
 
5
13
  ```ruby
6
14
  find_widget(widget_id)
7
- .and_then { |widget| update_widget(widget) }
8
- .on_success { |widget| logger.info("Updated #{widget}" }
9
- .on_failure { |error| logger.warn("Widget update failed because #{error}") }
15
+ .and_then { update_widget(_1) }
16
+ .on_success { logger.info("Updated #{_1}" }
17
+ .on_failure { logger.warn("Widget update failed because #{_1}") }
10
18
  ```
11
19
 
12
- Success type:
20
+ ## Success Type
21
+
22
+ A value that represents success. Wraps a `value` that can be any arbitrary
23
+ object.
13
24
 
14
25
  ```ruby
15
26
  result = Resonad.Success(5)
@@ -19,7 +30,10 @@ result.value #=> 5
19
30
  result.error #=> raises an exception
20
31
  ```
21
32
 
22
- Failure type:
33
+ ## Failure Type
34
+
35
+ A value that represents a failure. Wraps an `error` that can be any arbitrary
36
+ object.
23
37
 
24
38
  ```ruby
25
39
  result = Resonad.Failure(:buzz)
@@ -29,39 +43,199 @@ result.value #=> raises an exception
29
43
  result.error #=> :buzz
30
44
  ```
31
45
 
32
- Mapping monads:
46
+ ## Mapping
47
+
48
+ Non-destructive update for the `value` of a `Success` object. Does nothing to
49
+ `Failure` objects.
50
+
51
+ The block takes the `value` as an argument, and returns the new `value`.
33
52
 
34
53
  ```ruby
35
54
  result = Resonad.Success(5)
36
- .map { |i| i + 1 }
37
- .map { |i| i + 1 }
38
- .map { |i| i + 1 }
55
+ .map { _1 + 1 } # 5 + 1 -> 6
56
+ .map { _1 + 1 } # 6 + 1 -> 7
57
+ .map { _1 + 1 } # 7 + 1 -> 8
39
58
  result.success? #=> true
40
59
  result.value #=> 8
41
60
 
42
61
  result = Resonad.Failure(:buzz)
43
- .map { |i| i + 1 }
44
- .map { |i| i + 1 }
45
- .map { |i| i + 1 }
62
+ .map { _1 + 1 } # not run
63
+ .map { _1 + 1 } # not run
64
+ .map { _1 + 1 } # not run
46
65
  result.success? #=> false
47
66
  result.error #=> :buzz
48
67
  ```
49
68
 
50
- Flat mapping monads (a.k.a. `and_then`):
69
+
70
+ ## Aliases
71
+
72
+ Lots of the Resonad methods have aliases.
73
+
74
+ Personally, I can never remember if it's `success?` or `successful?` or `ok?`,
75
+ so let's just do it the Ruby way and allow all of them.
76
+
77
+ ```ruby
78
+ # >>> object creation aliases (same for failure) <<<
79
+ result = Resonad.Success(5)
80
+ result = Resonad.success(5) # lowercase, for those offended by capital letters
81
+ result = Resonad::Success[5] # class constructor method
82
+
83
+ # >>> success aliases <<<
84
+ result.success? #=> true
85
+ result.successful? #=> true
86
+ result.ok? #=> true
87
+
88
+ # >>> failure aliases <<<
89
+ result.failure? #=> false
90
+ result.failed? #=> false
91
+ result.bad? #=> false
92
+
93
+ # >>> mapping aliases <<<
94
+ result.map { _1 + 1 } #=> Success(6)
95
+ result.map_value { _1 + 1 } #=> Success(6)
96
+
97
+ # >>> flat mapping aliases <<<
98
+ result.and_then { Resonad.Success(_1 + 1) } #=> Success(6)
99
+ result.flat_map { Resonad.Success(_1 + 1) } #=> Success(6)
100
+
101
+ # >>> error flat mapping aliases <<<
102
+ result.or_else { Resonad.Failure(_1 + 1) } # not run
103
+ result.otherwise { Resonad.Failure(_1 + 1) } # not run
104
+ result.flat_map_error { Resonad.Success(_1 + 1) } # not run
105
+
106
+ # >>> conditional tap aliases <<<
107
+ # pattern: (on_|if_|when_)(success_alias|failure_alias)
108
+ result.on_success { puts "hi" } # outputs "hi"
109
+ result.if_success { puts "hi" } # outputs "hi"
110
+ result.when_success { puts "hi" } # outputs "hi"
111
+ result.on_ok { puts "hi" } # outputs "hi"
112
+ result.if_ok { puts "hi" } # outputs "hi"
113
+ result.when_ok { puts "hi" } # outputs "hi"
114
+ result.on_successful { puts "hi" } # outputs "hi"
115
+ result.if_successful { puts "hi" } # outputs "hi"
116
+ result.when_successful { puts "hi" } # outputs "hi"
117
+ result.on_failure { puts "hi" } # not run
118
+ result.if_failure { puts "hi" } # not run
119
+ result.when_failure { puts "hi" } # not run
120
+ result.on_bad { puts "hi" } # not run
121
+ result.if_bad { puts "hi" } # not run
122
+ result.when_bad { puts "hi" } # not run
123
+ result.on_failed { puts "hi" } # not run
124
+ result.if_failed { puts "hi" } # not run
125
+ result.when_failed { puts "hi" } # not run
126
+ ```
127
+
128
+
129
+ ## Flat Mapping (a.k.a. `and_then`)
130
+
131
+ Non-destructive update for a `Success` object. Either turns it into another
132
+ `Success` (can have a different `value`), or turns it into a `Failure`. Does
133
+ nothing to `Failure` objects.
134
+
135
+ The block takes the `value` as an argument, and returns a `Resonad` (either
136
+ `Success` or `Failure`).
51
137
 
52
138
  ```ruby
53
139
  result = Resonad.Success(5)
54
- .and_then { |i| Resonad.Success(i + 1) }
55
- .and_then { |i| Resonad.Failure("buzz #{i}") }
56
- .and_then { |i| Resonad.Success(i + 1) }
140
+ .and_then { Resonad.Success(_1 + 1) } # updates to Success(6)
141
+ .and_then { Resonad.Failure("buzz #{_1}") } # updates to Failure("buzz 6")
142
+ .and_then { Resonad.Success(_1 + 1) } # not run (because it's a failure)
57
143
  .error #=> "buzz 6"
58
144
 
59
- # can also use the less-nice `flat_map` method
60
- result
61
- .flat_map { |i| Resonad.Success(i + 1) }
145
+ # also has a less-friendly but more-technically-descriptive alias: `flat_map`
146
+ result.flat_map { Resonad.Success(_1 + 1) }
62
147
  ```
63
148
 
64
- Automatic exception rescuing:
149
+ This is different to Ruby's `#then` method added in 2.6. The block for `#then`
150
+ would take a Resonad argument, regardless of whether it's `Success` or
151
+ `Failure`. The block for `#and_then` takes a _`Success` object's value_, and
152
+ only runs on `Success` objects, not `Failure` objects.
153
+
154
+
155
+ ## Error Mapping
156
+
157
+ Just as `Success` objects can be chained with `#map` and `#and_then`, so can
158
+ `Failure` objects with `#map_error` and `#or_else`. This isn't used as often,
159
+ but has a few use cases such as:
160
+
161
+ ```ruby
162
+ # Use Case: convert an error value into another error value
163
+ make_http_request #=> Failure(404)
164
+ .map_error { |status_code| "HTTP #{status_code} Error" }
165
+ .error #=> "HTTP 404 Error"
166
+
167
+ # Use Case: recover from error, turning into Success
168
+ load_config_file #=> Failure(:config_file_missing)
169
+ .or_else { try_recover_from(_1) }
170
+ .value #=> { :setting => 'default' }
171
+
172
+ def try_recover_from(error)
173
+ if error == :config_file_missing
174
+ Resonad.Success({ setting: 'default' })
175
+ else
176
+ Resonad.Failure(error)
177
+ end
178
+ end
179
+ ```
180
+
181
+
182
+ ## Conditional Tap
183
+
184
+ If you're in the middle of a long chain of methods, and you don't want to break
185
+ the chain to run some kind of side effect, you can use the `#on_success` and
186
+ `#on_failure` methods. These run an arbitrary block code, but do not affect the
187
+ result object in any way. They work like Ruby's `#tap` method, but `Failure`
188
+ objects will not run `on_success` blocks, and `Success` objects will not run
189
+ `on_failure` blocks.
190
+
191
+ ```ruby
192
+ do_step_1
193
+ .and_then { do_step_2(_1) }
194
+ .and_then { do_step_3(_1) }
195
+ .on_success { puts "Successful step 3 result: #{_1}" }
196
+ .and_then { do_step_4(_1) }
197
+ .and_then { do_step_5(_1) }
198
+ .on_failure { puts "Uh oh! Step 5 failed: #{_1} }
199
+ .and_then { do_step_6(_1) }
200
+ .and_then { do_step_7(_1) }
201
+ ```
202
+
203
+ There are lots of aliases for these methods. See the "Aliases" section above.
204
+
205
+
206
+ ## Pattern Matching Support
207
+
208
+ If you are using Ruby 2.7 or later, you can pattern match on Resonad objects.
209
+ For example:
210
+
211
+ ```ruby
212
+ case result
213
+ in { value: } # match any Success
214
+ puts value
215
+ in { error: :not_found } # match Failure(:not_found)
216
+ puts "Thing not found"
217
+ in { error: String => msg } # match any Failure with a String error
218
+ puts "Failed to fetch thing because #{msg}"
219
+ in { error: } # match any Failure
220
+ raise "Unhandled error: #{error.inspect}"
221
+ end
222
+ ```
223
+
224
+ `Resonad.Success(5)` deconstructs to:
225
+
226
+ - Hash: `{ value: 5 }`
227
+ - Array: `[:success, 5]`
228
+
229
+ And `Resonad.Failure('yikes')` deconstructs to:
230
+
231
+ - Hash: `{ error: 'yikes' }`
232
+ - Array: `[:failure, 'yikes']`
233
+
234
+
235
+ ## Automatic Exception Rescuing
236
+
237
+ If no exception is raised, wraps the block's return value in `Success`. If an
238
+ exception is raised, wraps the exception object in `Failure`.
65
239
 
66
240
  ```ruby
67
241
  def try_divide(top, bottom)
@@ -76,3 +250,55 @@ nope = try_divide(6, 0)
76
250
  nope.success? #=> false
77
251
  node.error #=> #<ZeroDivisionError: ZeroDivisionError>
78
252
  ```
253
+
254
+
255
+ ## Convenience Mixin
256
+
257
+ If you're tired of typing "Resonad." in front of everything, you can include
258
+ the `Resonad::Mixin` mixin.
259
+
260
+ ```ruby
261
+ class RobotFortuneTeller
262
+ include Resonad::Mixin
263
+
264
+ def next_fortune
265
+ case rand(0..100)
266
+ when 0..70
267
+ # title-case constructor from Resonad::Mixin
268
+ Success("today is auspicious")
269
+ when 71..95
270
+ # lower-case constructor from Resonad::Mixin
271
+ success("ill omens abound")
272
+ else
273
+ # direct access to classes from Resonad::Mixin
274
+ Failure.new("MALFUNCTION")
275
+ end
276
+ end
277
+ end
278
+ ```
279
+
280
+ Note that `Resonad::Mixin` provides private methods, and private constants, so
281
+ you can't do this:
282
+
283
+ ```ruby
284
+ RobotFortuneTeller.new.Success(5)
285
+ #=> NoMethodError: private method `Success' called for #<RobotFortuneTeller:0x00007fe7fc0ff0c8>
286
+
287
+ RobotFortuneTeller::Success
288
+ #=> NameError: private constant Resonad::Mixin::Success referenced
289
+ ```
290
+
291
+ If you want the methods/constants to be public, then use `Resonad::PublicMixin`
292
+ instead.
293
+
294
+
295
+ ## Contributing
296
+
297
+ Bug reports and pull requests are welcome on GitHub at:
298
+ https://github.com/tomdalling/resonad
299
+
300
+ I'm open to PRs that make the gem more convenient, or that makes calling code
301
+ read better.
302
+
303
+ Make sure your PR has full test coverage.
304
+
@@ -2,28 +2,17 @@ class Resonad
2
2
  class NonExistentError < StandardError; end
3
3
  class NonExistentValue < StandardError; end
4
4
 
5
- module Mixin
6
- def Success(value=nil)
5
+ class Success < Resonad
6
+ attr_accessor :value
7
+
8
+ def self.[](value = nil)
7
9
  if nil == value
8
10
  NIL_SUCCESS
9
11
  else
10
- Success.new(value)
12
+ new(value)
11
13
  end
12
14
  end
13
15
 
14
- def Failure(error=nil)
15
- if nil == error
16
- NIL_FAILURE
17
- else
18
- Failure.new(error)
19
- end
20
- end
21
- end
22
- extend Mixin
23
-
24
- class Success < Resonad
25
- attr_accessor :value
26
-
27
16
  def initialize(value)
28
17
  @value = value
29
18
  freeze
@@ -66,11 +55,27 @@ class Resonad
66
55
  def flat_map_error
67
56
  self
68
57
  end
58
+
59
+ def deconstruct
60
+ [:success, value]
61
+ end
62
+
63
+ def deconstruct_keys(_)
64
+ { value: value }
65
+ end
69
66
  end
70
67
 
71
68
  class Failure < Resonad
72
69
  attr_accessor :error
73
70
 
71
+ def self.[](error = nil)
72
+ if nil == error
73
+ NIL_FAILURE
74
+ else
75
+ new(error)
76
+ end
77
+ end
78
+
74
79
  def initialize(error)
75
80
  @error = error
76
81
  freeze
@@ -113,8 +118,35 @@ class Resonad
113
118
  def flat_map_error
114
119
  yield error
115
120
  end
121
+
122
+ def deconstruct
123
+ [:failure, error]
124
+ end
125
+
126
+ def deconstruct_keys(_)
127
+ { error: error }
128
+ end
116
129
  end
117
130
 
131
+ module PublicMixin
132
+ Success = ::Resonad::Success
133
+ Failure = ::Resonad::Failure
134
+
135
+ def Success(*args); Success[*args]; end
136
+ def success(*args); Success[*args]; end
137
+ def Failure(*args); Failure[*args]; end
138
+ def failure(*args); Failure[*args]; end
139
+ end
140
+
141
+ Mixin = PublicMixin.dup.tap do |mixin|
142
+ mixin.module_eval do
143
+ private(*public_instance_methods)
144
+ private_constant(*constants)
145
+ end
146
+ end
147
+
148
+ extend PublicMixin
149
+
118
150
  def self.rescuing_from(*exception_classes)
119
151
  Success(yield)
120
152
  rescue Exception => e
@@ -143,6 +175,11 @@ class Resonad
143
175
  def failed?; failure?; end
144
176
  def bad?; failure?; end
145
177
 
178
+ def map(&block)
179
+ raise NotImplementedError, "should be implemented in subclass"
180
+ end
181
+ def map_value(&block); map(&block); end
182
+
146
183
  def flat_map
147
184
  raise NotImplementedError, "should be implemented in subclass"
148
185
  end
@@ -152,6 +189,31 @@ class Resonad
152
189
  raise NotImplementedError, "should be implemented in subclass"
153
190
  end
154
191
  def or_else(&block); flat_map_error(&block); end
192
+ def otherwise(&block); flat_map_error(&block); end
193
+
194
+ def on_success(&block)
195
+ raise NotImplementedError, "should be implemented in subclass"
196
+ end
197
+ def if_success(&block); on_success(&block); end
198
+ def when_success(&block); on_success(&block); end
199
+ def on_ok(&block); on_success(&block); end
200
+ def if_ok(&block); on_success(&block); end
201
+ def when_ok(&block); on_success(&block); end
202
+ def on_successful(&block); on_success(&block); end
203
+ def if_successful(&block); on_success(&block); end
204
+ def when_successful(&block); on_success(&block); end
205
+
206
+ def on_failure(&block)
207
+ raise NotImplementedError, "should be implemented in subclass"
208
+ end
209
+ def if_failure(&block); on_failure(&block); end
210
+ def when_failure(&block); on_failure(&block); end
211
+ def on_bad(&block); on_failure(&block); end
212
+ def if_bad(&block); on_failure(&block); end
213
+ def when_bad(&block); on_failure(&block); end
214
+ def on_failed(&block); on_failure(&block); end
215
+ def if_failed(&block); on_failure(&block); end
216
+ def when_failed(&block); on_failure(&block); end
155
217
 
156
218
  NIL_SUCCESS = Success.new(nil)
157
219
  NIL_FAILURE = Failure.new(nil)
@@ -1,3 +1,3 @@
1
1
  class Resonad
2
- VERSION = '1.2.0'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -20,8 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.14"
24
- spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "bundler", ">= 1.15"
25
24
  spec.add_development_dependency "rspec", "~> 3.0"
26
- spec.add_development_dependency "gem-release", "~> 0.7"
25
+ spec.add_development_dependency "gem-release", "~> 2.1"
27
26
  end
metadata CHANGED
@@ -1,43 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resonad
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Dalling
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-22 00:00:00.000000000 Z
11
+ date: 2020-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.14'
19
+ version: '1.15'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.14'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '10.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
24
+ - - ">="
39
25
  - !ruby/object:Gem::Version
40
- version: '10.0'
26
+ version: '1.15'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rspec
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +44,14 @@ dependencies:
58
44
  requirements:
59
45
  - - "~>"
60
46
  - !ruby/object:Gem::Version
61
- version: '0.7'
47
+ version: '2.1'
62
48
  type: :development
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
52
  - - "~>"
67
53
  - !ruby/object:Gem::Version
68
- version: '0.7'
54
+ version: '2.1'
69
55
  description: Objects that represent success or failure
70
56
  email:
71
57
  - tom@tomdalling.com
@@ -75,12 +61,13 @@ extra_rdoc_files: []
75
61
  files:
76
62
  - ".gitignore"
77
63
  - ".rspec"
64
+ - ".ruby-version"
78
65
  - ".travis.yml"
66
+ - CHANGELOG.md
79
67
  - CODE_OF_CONDUCT.md
80
68
  - Gemfile
81
69
  - LICENSE.txt
82
70
  - README.md
83
- - Rakefile
84
71
  - bin/console
85
72
  - bin/setup
86
73
  - lib/resonad.rb
@@ -106,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
93
  version: '0'
107
94
  requirements: []
108
95
  rubyforge_project:
109
- rubygems_version: 2.4.5
96
+ rubygems_version: 2.7.7
110
97
  signing_key:
111
98
  specification_version: 4
112
99
  summary: Objects that represent success or failure
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec