fulfil-io 0.7.0 → 0.8.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/README.md +31 -1
- data/Rakefile +8 -6
- data/lib/fulfil/client.rb +7 -7
- data/lib/fulfil/configuration.rb +13 -0
- data/lib/fulfil/interactive_report.rb +3 -1
- data/lib/fulfil/model.rb +6 -4
- data/lib/fulfil/query.rb +20 -16
- data/lib/fulfil/rate_limit.rb +13 -2
- data/lib/fulfil/response_parser.rb +14 -8
- data/lib/fulfil/version.rb +1 -1
- metadata +8 -110
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e82498f50af6f27434982cbeb6bb3faec54a085e999f4d86293d4378afb801a
|
4
|
+
data.tar.gz: d2596d9afedaf2f67aa3f573c139d1c5a03b706e638fdf2407fc482f25336d6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67ad033ab2a666abc04747a37e1d4859690158cfdf1c6455cdc3e3383ccfd6aa74b556def1b02e7584945120b426357ed4a85fa1f1feaa74ad118fbe6161280c
|
7
|
+
data.tar.gz: 1ade1a109a650b56c76fcaea49ed71d92b87d8f87e6659748ea5c739d6e6f1715ec6099835f2faefd7c515e8482054d580c17b0fcb74342c2cc214d40fabaeee
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
[](https://github.com/knowndecimal/fulfil/actions/workflows/tests.yml)
|
2
|
+
[](https://codeclimate.com/github/knowndecimal/fulfil/maintainability)
|
3
|
+
[](https://codeclimate.com/github/knowndecimal/fulfil/test_coverage)
|
2
4
|
|
3
5
|
# Fulfil.io Rubygem
|
4
6
|
|
@@ -146,6 +148,8 @@ $ Fulfil.rate_limit.resets_at
|
|
146
148
|
=> #<DateTime: 2022-01-21T16:36:01-04:00 />
|
147
149
|
```
|
148
150
|
|
151
|
+
### Automatic retry API call after rate limit hit
|
152
|
+
|
149
153
|
Automatic retries are supported whenever the rate limit is reached. However, it's not enabled by default. To enable it, set the `retry_on_rate_limit` to `true`. By default, the request will be retried in 1 second.
|
150
154
|
|
151
155
|
```ruby
|
@@ -157,6 +161,32 @@ Fulfil.configure do |config|
|
|
157
161
|
end
|
158
162
|
```
|
159
163
|
|
164
|
+
### Monitor rate limit hits
|
165
|
+
|
166
|
+
Through the configurable `rate_limit_notification_handler` one can monitor the rate limit hits to the APM tool of choice.
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
# config/initializers/fulfil.rb
|
170
|
+
|
171
|
+
Fulfil.configure do |config|
|
172
|
+
config.rate_limit_notification_handler = proc {
|
173
|
+
FakeAPM.increment_counter('fulfil.rate_limit_exceeded')
|
174
|
+
}
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
## Retrieve multiple records
|
179
|
+
|
180
|
+
To retrieve multiple records at once, one can pass the IDs into the find method directly.
|
181
|
+
|
182
|
+
```ruby
|
183
|
+
FulfilClient.find(
|
184
|
+
model: 'sale.sale',
|
185
|
+
ids: [1, 2, 3, 4],
|
186
|
+
fields: %w[id status]
|
187
|
+
)
|
188
|
+
```
|
189
|
+
|
160
190
|
## Development
|
161
191
|
|
162
192
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
@@ -197,7 +227,7 @@ def test_find_one
|
|
197
227
|
stub_fulfil_get('sale.sale/213112', 'sale_sale')
|
198
228
|
|
199
229
|
client = Fulfil::Client.new
|
200
|
-
response = client.
|
230
|
+
response = client.find(model: 'sale.sale', id: 213_112)
|
201
231
|
|
202
232
|
assert_equal 213_112, response['id']
|
203
233
|
end
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
3
5
|
|
4
6
|
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs <<
|
6
|
-
t.libs <<
|
7
|
-
t.test_files = FileList[
|
7
|
+
t.libs << 'test'
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
10
|
end
|
9
11
|
|
10
|
-
task :
|
12
|
+
task default: :test
|
data/lib/fulfil/client.rb
CHANGED
@@ -5,8 +5,8 @@ require 'logger'
|
|
5
5
|
require 'fulfil/response_parser'
|
6
6
|
|
7
7
|
module Fulfil
|
8
|
-
SUBDOMAIN = ENV
|
9
|
-
API_KEY = ENV
|
8
|
+
SUBDOMAIN = ENV.fetch('FULFIL_SUBDOMAIN', nil)
|
9
|
+
API_KEY = ENV.fetch('FULFIL_API_KEY', nil)
|
10
10
|
|
11
11
|
class Client
|
12
12
|
class InvalidClientError < StandardError
|
@@ -93,6 +93,7 @@ module Fulfil
|
|
93
93
|
uri = URI(model_url(model: model, id: id, endpoint: endpoint))
|
94
94
|
|
95
95
|
result = request(verb: :put, endpoint: uri, json: body)
|
96
|
+
|
96
97
|
parse(result: result)
|
97
98
|
end
|
98
99
|
|
@@ -114,10 +115,10 @@ module Fulfil
|
|
114
115
|
def oauth_token
|
115
116
|
if ENV['FULFIL_TOKEN']
|
116
117
|
puts "You're using an deprecated environment variable. Please update your " \
|
117
|
-
|
118
|
+
'FULFIL_TOKEN to FULFIL_OAUTH_TOKEN.'
|
118
119
|
end
|
119
120
|
|
120
|
-
ENV['FULFIL_OAUTH_TOKEN'] || ENV
|
121
|
+
ENV['FULFIL_OAUTH_TOKEN'] || ENV.fetch('FULFIL_TOKEN', nil)
|
121
122
|
end
|
122
123
|
|
123
124
|
def parse(result: nil, results: [])
|
@@ -174,10 +175,9 @@ module Fulfil
|
|
174
175
|
end
|
175
176
|
|
176
177
|
def client
|
177
|
-
client = HTTP.use(logging: @debug ? { logger: Logger.new(
|
178
|
+
client = HTTP.use(logging: @debug ? { logger: Logger.new($stdout) } : {})
|
178
179
|
client = client.auth("Bearer #{@token}") if @token
|
179
|
-
client
|
180
|
-
client
|
180
|
+
client.headers(@headers)
|
181
181
|
end
|
182
182
|
|
183
183
|
def config
|
data/lib/fulfil/configuration.rb
CHANGED
@@ -9,6 +9,19 @@ module Fulfil
|
|
9
9
|
attr_accessor :retry_on_rate_limit
|
10
10
|
attr_accessor :retry_on_rate_limit_wait
|
11
11
|
|
12
|
+
# Allows the client to configure a notification handler. Can be used by APM
|
13
|
+
# tools to monitor the number of rate limit hits.
|
14
|
+
#
|
15
|
+
# @example Use APM to monitor the API rate limit hits
|
16
|
+
# Fulfil.configure do |config|
|
17
|
+
# config.rate_limit_notification_handler = proc {
|
18
|
+
# FakeAPM.increment_counter('fulfil.rate_limit_exceeded')
|
19
|
+
# }
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# @return [Proc, nil]
|
23
|
+
attr_accessor :rate_limit_notification_handler
|
24
|
+
|
12
25
|
def initialize
|
13
26
|
@retry_on_rate_limit = false
|
14
27
|
@retry_on_rate_limit_wait = 1
|
data/lib/fulfil/model.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fulfil/query'
|
2
4
|
|
3
5
|
module Fulfil
|
@@ -12,15 +14,15 @@ module Fulfil
|
|
12
14
|
|
13
15
|
# Delegate this to the client, including the model_name so we don't have to
|
14
16
|
# type it every time.
|
15
|
-
def find(model: model_name
|
17
|
+
def find(id:, model: model_name)
|
16
18
|
@client.find(model: model, id: id)
|
17
19
|
end
|
18
20
|
|
19
21
|
# Delegate this to the client, including the model_name so we don't have to
|
20
22
|
# type it every time.
|
21
23
|
def search(
|
22
|
-
model: model_name,
|
23
24
|
domain:,
|
25
|
+
model: model_name,
|
24
26
|
fields: %w[id rec_name],
|
25
27
|
limit: nil,
|
26
28
|
offset: nil,
|
@@ -51,7 +53,7 @@ module Fulfil
|
|
51
53
|
|
52
54
|
def attributes
|
53
55
|
results = @client.search(model: model_name, domain: [], limit: 1)
|
54
|
-
@client.find(model: model_name, id: results.first
|
56
|
+
@client.find(model: model_name, id: results.first['id'])
|
55
57
|
end
|
56
58
|
|
57
59
|
def fetch_associated(models:, association_name:, source_key:, fields:)
|
@@ -66,7 +68,7 @@ module Fulfil
|
|
66
68
|
model: association_name, ids: associated_ids, fields: fields
|
67
69
|
)
|
68
70
|
|
69
|
-
associated_models_by_id = associated_models.
|
71
|
+
associated_models_by_id = associated_models.to_h { |m| [m['id'], m] }
|
70
72
|
|
71
73
|
models.each do |model|
|
72
74
|
filtered_models =
|
data/lib/fulfil/query.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Fulfil
|
2
4
|
class Query
|
3
5
|
def initialize
|
@@ -9,11 +11,12 @@ module Fulfil
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def search(*args)
|
12
|
-
options = args.first { |arg| arg.is_a?(Hash) && arg.
|
14
|
+
options = args.first { |arg| arg.is_a?(Hash) && arg.key?(:options) }.fetch(:options, {})
|
13
15
|
|
14
16
|
args.each do |arg|
|
15
17
|
arg.each do |field, value|
|
16
18
|
next if value == options
|
19
|
+
|
17
20
|
@matchers.concat(build_search_term(field: field, value: value, options: options))
|
18
21
|
end
|
19
22
|
end
|
@@ -22,17 +25,18 @@ module Fulfil
|
|
22
25
|
end
|
23
26
|
|
24
27
|
def exclude(*args)
|
25
|
-
options = args.first { |arg| arg.is_a?(Hash) && arg.
|
28
|
+
options = args.first { |arg| arg.is_a?(Hash) && arg.key?(:options) }.fetch(:options, {})
|
26
29
|
|
27
30
|
terms = args.flat_map do |arg|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
arg.map do |field, value|
|
32
|
+
next if value == options
|
33
|
+
|
34
|
+
build_exclude_term(field: field, value: value, options: options)
|
35
|
+
end
|
36
|
+
end
|
33
37
|
|
34
38
|
if terms.length > 1
|
35
|
-
@matchers.push([
|
39
|
+
@matchers.push(['OR'].concat(terms))
|
36
40
|
else
|
37
41
|
@matchers.concat(terms.first)
|
38
42
|
end
|
@@ -62,7 +66,7 @@ module Fulfil
|
|
62
66
|
#
|
63
67
|
# IN, NOT IN: (Array)
|
64
68
|
#
|
65
|
-
def build_search_term(
|
69
|
+
def build_search_term(field:, value:, options:, prefix: nil)
|
66
70
|
key = [prefix, field.to_s].compact.join('.')
|
67
71
|
|
68
72
|
case value.class.name
|
@@ -73,7 +77,7 @@ module Fulfil
|
|
73
77
|
when 'Range'
|
74
78
|
[
|
75
79
|
[key, '>=', value.first],
|
76
|
-
[key, '<=', value.last]
|
80
|
+
[key, '<=', value.last]
|
77
81
|
]
|
78
82
|
when 'String'
|
79
83
|
if options[:case_sensitive]
|
@@ -82,15 +86,15 @@ module Fulfil
|
|
82
86
|
[[key, 'ilike', value]]
|
83
87
|
end
|
84
88
|
when 'Hash'
|
85
|
-
value.flat_map
|
89
|
+
value.flat_map do |nested_field, nested_value|
|
86
90
|
build_search_term(prefix: field, field: nested_field, value: nested_value, options: options)
|
87
|
-
|
91
|
+
end
|
88
92
|
else
|
89
93
|
raise "Unhandled value type: #{value} (#{value.class.name})"
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
93
|
-
def build_exclude_term(
|
97
|
+
def build_exclude_term(field:, value:, options:, prefix: nil)
|
94
98
|
key = [prefix, field.to_s].compact.join('.')
|
95
99
|
|
96
100
|
case value.class.name
|
@@ -101,12 +105,12 @@ module Fulfil
|
|
101
105
|
when 'Range'
|
102
106
|
[
|
103
107
|
[key, '<', value.first],
|
104
|
-
[key, '>', value.last]
|
108
|
+
[key, '>', value.last]
|
105
109
|
]
|
106
110
|
when 'Hash'
|
107
|
-
value.flat_map
|
111
|
+
value.flat_map do |nested_field, nested_value|
|
108
112
|
build_exclude_term(prefix: field, field: nested_field, value: nested_value, options: options)
|
109
|
-
|
113
|
+
end
|
110
114
|
else
|
111
115
|
raise "Unhandled value type: #{value} (#{value.class.name})"
|
112
116
|
end
|
data/lib/fulfil/rate_limit.rb
CHANGED
@@ -8,7 +8,8 @@ module Fulfil
|
|
8
8
|
|
9
9
|
# Analyses the rate limit based on the response headers from Fulfil.
|
10
10
|
# @param headers [HTTP::Headers] The HTTP response headers from Fulfil.
|
11
|
-
# @
|
11
|
+
# @raise [Fulfil::RateLimitExceeded] When the rate limit is hit.
|
12
|
+
# @return [true]
|
12
13
|
def analyse!(headers)
|
13
14
|
rate_limit_headers = RateLimitHeaders.new(headers)
|
14
15
|
|
@@ -16,7 +17,9 @@ module Fulfil
|
|
16
17
|
self.requests_left = rate_limit_headers.requests_left
|
17
18
|
self.resets_at = rate_limit_headers.resets_at
|
18
19
|
|
19
|
-
|
20
|
+
return true if requests_left?
|
21
|
+
|
22
|
+
report_rate_limit_hit_and_raise
|
20
23
|
end
|
21
24
|
|
22
25
|
# Returns whether there are any requests left in the current rate limit window.
|
@@ -24,5 +27,13 @@ module Fulfil
|
|
24
27
|
def requests_left?
|
25
28
|
requests_left&.positive?
|
26
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# @raise [Fulfil::RateLimitExceeded]
|
34
|
+
def report_rate_limit_hit_and_raise
|
35
|
+
Fulfil.config.rate_limit_notification_handler&.call
|
36
|
+
raise Fulfil::RateLimitExceeded
|
37
|
+
end
|
27
38
|
end
|
28
39
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Fulfil
|
2
4
|
module ResponseParser
|
3
5
|
class UnhandledTypeError < StandardError
|
@@ -17,19 +19,19 @@ module Fulfil
|
|
17
19
|
# }
|
18
20
|
#
|
19
21
|
def self.mapped_value_field(value:)
|
20
|
-
return value unless value.is_a?(Hash) && value
|
22
|
+
return value unless value.is_a?(Hash) && value['__class__']
|
21
23
|
|
22
|
-
json_class = value
|
24
|
+
json_class = value['__class__']
|
23
25
|
|
24
26
|
case json_class
|
25
27
|
when 'date'
|
26
|
-
date = value
|
28
|
+
date = value['iso_string']
|
27
29
|
Date.parse(date)
|
28
30
|
when 'datetime'
|
29
|
-
time = value
|
31
|
+
time = value['iso_string']
|
30
32
|
DateTime.parse(time)
|
31
33
|
when 'Decimal', 'timedelta'
|
32
|
-
value
|
34
|
+
value['decimal'].to_f
|
33
35
|
else
|
34
36
|
raise UnhandledTypeError.new(
|
35
37
|
"received a value that we don't know how to handle: #{json_class}",
|
@@ -46,15 +48,19 @@ module Fulfil
|
|
46
48
|
[group_key, mapped_value_field(value: kv_tuples[0][1])]
|
47
49
|
else
|
48
50
|
id = kv_tuples[0]
|
49
|
-
attrs = kv_tuples[1
|
51
|
+
attrs = kv_tuples[1..].map { |tuple| [tuple[0][1..], tuple[1]] }
|
50
52
|
[group_key, [['id', id[1]]].concat(group(attrs)).to_h]
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
55
57
|
def self.parse(item:)
|
56
|
-
|
57
|
-
|
58
|
+
case item
|
59
|
+
when Hash
|
60
|
+
group(item.map { |(key, value)| [key.split('.'), value] }).to_h
|
61
|
+
else
|
62
|
+
item
|
63
|
+
end
|
58
64
|
end
|
59
65
|
end
|
60
66
|
end
|
data/lib/fulfil/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fulfil-io
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Moore
|
8
8
|
- Kat Fairbanks
|
9
|
+
- Stefan Vermaas
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2023-04-20 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: http
|
@@ -20,7 +21,7 @@ dependencies:
|
|
20
21
|
version: 4.4.1
|
21
22
|
- - "<"
|
22
23
|
- !ruby/object:Gem::Version
|
23
|
-
version: 5.
|
24
|
+
version: 5.2.0
|
24
25
|
type: :runtime
|
25
26
|
prerelease: false
|
26
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -30,111 +31,7 @@ dependencies:
|
|
30
31
|
version: 4.4.1
|
31
32
|
- - "<"
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: 5.
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: bundler
|
36
|
-
requirement: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2.0'
|
41
|
-
type: :development
|
42
|
-
prerelease: false
|
43
|
-
version_requirements: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '2.0'
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: minitest
|
50
|
-
requirement: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '5.0'
|
55
|
-
type: :development
|
56
|
-
prerelease: false
|
57
|
-
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '5.0'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: minitest-reporters
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '1.3'
|
69
|
-
type: :development
|
70
|
-
prerelease: false
|
71
|
-
version_requirements: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - "~>"
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '1.3'
|
76
|
-
- !ruby/object:Gem::Dependency
|
77
|
-
name: oauth2
|
78
|
-
requirement: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - "~>"
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '1.4'
|
83
|
-
type: :development
|
84
|
-
prerelease: false
|
85
|
-
version_requirements: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1.4'
|
90
|
-
- !ruby/object:Gem::Dependency
|
91
|
-
name: rake
|
92
|
-
requirement: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
type: :development
|
98
|
-
prerelease: false
|
99
|
-
version_requirements: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
- !ruby/object:Gem::Dependency
|
105
|
-
name: webmock
|
106
|
-
requirement: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
|
-
type: :development
|
112
|
-
prerelease: false
|
113
|
-
version_requirements: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
- !ruby/object:Gem::Dependency
|
119
|
-
name: dotenv
|
120
|
-
requirement: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - "~>"
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '2.7'
|
125
|
-
- - ">="
|
126
|
-
- !ruby/object:Gem::Version
|
127
|
-
version: 2.7.6
|
128
|
-
type: :development
|
129
|
-
prerelease: false
|
130
|
-
version_requirements: !ruby/object:Gem::Requirement
|
131
|
-
requirements:
|
132
|
-
- - "~>"
|
133
|
-
- !ruby/object:Gem::Version
|
134
|
-
version: '2.7'
|
135
|
-
- - ">="
|
136
|
-
- !ruby/object:Gem::Version
|
137
|
-
version: 2.7.6
|
34
|
+
version: 5.2.0
|
138
35
|
description:
|
139
36
|
email:
|
140
37
|
- chris@knowndecimal.com
|
@@ -165,7 +62,8 @@ files:
|
|
165
62
|
homepage: https://github.com/knowndecimal/fulfil
|
166
63
|
licenses:
|
167
64
|
- MIT
|
168
|
-
metadata:
|
65
|
+
metadata:
|
66
|
+
rubygems_mfa_required: 'true'
|
169
67
|
post_install_message:
|
170
68
|
rdoc_options: []
|
171
69
|
require_paths:
|
@@ -174,7 +72,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
174
72
|
requirements:
|
175
73
|
- - ">="
|
176
74
|
- !ruby/object:Gem::Version
|
177
|
-
version: '2.
|
75
|
+
version: '2.6'
|
178
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
77
|
requirements:
|
180
78
|
- - ">="
|