userlist 1.0.0 → 1.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/.rubocop.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/Gemfile +5 -0
- data/lib/userlist/config.rb +2 -2
- data/lib/userlist/delivery_method.rb +3 -0
- data/lib/userlist/push/company.rb +1 -1
- data/lib/userlist/push/event.rb +1 -1
- data/lib/userlist/push/message.rb +2 -1
- data/lib/userlist/push/operations/delete.rb +2 -1
- data/lib/userlist/push/operations/{create.rb → push.rb} +6 -8
- data/lib/userlist/push/relationship.rb +1 -1
- data/lib/userlist/push/resource.rb +21 -14
- data/lib/userlist/push/serializer.rb +25 -12
- data/lib/userlist/push/strategies/active_job.rb +1 -1
- data/lib/userlist/push/strategies/sidekiq.rb +1 -1
- data/lib/userlist/push/strategies/threaded/worker.rb +6 -8
- data/lib/userlist/push/user.rb +1 -1
- data/lib/userlist/push.rb +10 -10
- data/lib/userlist/retryable.rb +8 -10
- data/lib/userlist/version.rb +1 -1
- data/userlist.gemspec +2 -8
- metadata +6 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ed2e089f640ba0d4865236a53b5744e9edfbbe4400337b789c6e09c80474870
|
4
|
+
data.tar.gz: ce7ad3b24cc47645ee91d69aa27f312628f840c427c52f49ae38823abf9ad1d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c0b7d45d3edcb1a07e10e759b6d3911ff594f6feceadc7fb17eef9961ea693853e570e9223ce837cc11cc04b025fd227ed42ba4c5e35501406f9a636d39f22b
|
7
|
+
data.tar.gz: 64146b1ba4fda2069e74e230e81c7d1447166b03775fe048ba821d7ec04702ab69ea85a116ffb0243f4f3a4e01b83e7e53c28fef7813f9351851428bd6343743
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
## Unreleased (main)
|
4
4
|
|
5
|
+
## v1.1.0 (2025-10-17)
|
6
|
+
|
7
|
+
- Allow specifying companies in messages
|
8
|
+
- Add reply_to support to DeliveryMethod for ActionMailer integration
|
9
|
+
- Fixes issue with deleting resources when they are not pushed by default
|
10
|
+
|
5
11
|
## v1.0.0 (2025-04-08)
|
6
12
|
|
7
13
|
- Updates ActiveJob Worker to retry on errors with polynomially longer wait times, up to 10 attempts
|
data/Gemfile
CHANGED
@@ -4,6 +4,11 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
4
4
|
|
5
5
|
gemspec
|
6
6
|
|
7
|
+
gem 'jwt', '~> 2.2'
|
8
|
+
gem 'rake', '~> 13.0'
|
9
|
+
gem 'rspec', '~> 3.0'
|
10
|
+
gem 'webmock', '~> 3.18'
|
11
|
+
|
7
12
|
gem 'guard-rspec', '~> 4.7'
|
8
13
|
gem 'guard-rubocop', '~> 1.3'
|
9
14
|
gem 'rubocop', '~> 1.45'
|
data/lib/userlist/config.rb
CHANGED
@@ -75,12 +75,12 @@ module Userlist
|
|
75
75
|
key?(name.to_sym) || super
|
76
76
|
end
|
77
77
|
|
78
|
-
def method_missing(name,
|
78
|
+
def method_missing(name, ...)
|
79
79
|
if respond_to_missing?(name)
|
80
80
|
name = name.to_s
|
81
81
|
method = name =~ /=$/ ? :[]= : :[]
|
82
82
|
name = name.sub(/=$/, '').to_sym
|
83
|
-
send(method, name,
|
83
|
+
send(method, name, ...)
|
84
84
|
else
|
85
85
|
super
|
86
86
|
end
|
@@ -19,12 +19,15 @@ private
|
|
19
19
|
{
|
20
20
|
to: serialize_address(mail.to),
|
21
21
|
from: serialize_address(mail.from),
|
22
|
+
reply_to: serialize_address(mail.reply_to),
|
22
23
|
subject: mail.subject,
|
23
24
|
body: serialize_body(mail.body)
|
24
25
|
}.compact
|
25
26
|
end
|
26
27
|
|
27
28
|
def serialize_address(address)
|
29
|
+
return if address.nil? || Array(address).empty?
|
30
|
+
|
28
31
|
Array(address).map(&:to_s)
|
29
32
|
end
|
30
33
|
|
data/lib/userlist/push/event.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Userlist
|
2
2
|
class Push
|
3
3
|
class Message < Resource
|
4
|
-
include Operations::
|
4
|
+
include Operations::Push
|
5
5
|
|
6
6
|
has_one :user, type: 'Userlist::Push::User'
|
7
|
+
has_one :company, type: 'Userlist::Push::Company'
|
7
8
|
|
8
9
|
def initialize(payload = {}, config = Userlist.config)
|
9
10
|
raise Userlist::ArgumentError, 'Missing required payload' unless payload
|
@@ -5,8 +5,9 @@ module Userlist
|
|
5
5
|
module ClassMethods
|
6
6
|
def delete(payload = {}, config = self.config)
|
7
7
|
return false unless resource = from_payload(payload, config)
|
8
|
+
return false unless resource.delete?
|
8
9
|
|
9
|
-
strategy.call(:delete, endpoint, resource
|
10
|
+
strategy.call(:delete, endpoint, resource.for_context(:delete))
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -1,24 +1,22 @@
|
|
1
1
|
module Userlist
|
2
2
|
class Push
|
3
3
|
module Operations
|
4
|
-
module
|
4
|
+
module Push
|
5
5
|
module ClassMethods
|
6
|
-
def
|
6
|
+
def push(payload = {}, config = self.config)
|
7
7
|
return false unless resource = from_payload(payload, config)
|
8
|
+
return false unless resource.push?
|
8
9
|
|
9
|
-
strategy.call(:post, endpoint, resource)
|
10
|
+
strategy.call(:post, endpoint, resource.for_context(:push))
|
10
11
|
end
|
11
12
|
|
12
|
-
alias push
|
13
|
+
alias create push
|
14
|
+
alias update push
|
13
15
|
end
|
14
16
|
|
15
17
|
def self.included(base)
|
16
18
|
base.extend(ClassMethods)
|
17
19
|
end
|
18
|
-
|
19
|
-
def create?
|
20
|
-
push?
|
21
|
-
end
|
22
20
|
end
|
23
21
|
end
|
24
22
|
end
|
@@ -19,18 +19,18 @@ module Userlist
|
|
19
19
|
new(payload, config)
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
@
|
22
|
+
def association_names
|
23
|
+
@association_names ||= associations.keys
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
@
|
26
|
+
def associations
|
27
|
+
@associations ||= {}
|
28
28
|
end
|
29
29
|
|
30
30
|
protected
|
31
31
|
|
32
32
|
def has_one(name, type:) # rubocop:disable Naming/PredicateName
|
33
|
-
|
33
|
+
associations[name.to_sym] = { type: type }
|
34
34
|
|
35
35
|
generated_methods.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
36
36
|
def #{name} # def company
|
@@ -40,14 +40,14 @@ module Userlist
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def has_many(name, **options) # rubocop:disable Naming/PredicateName
|
43
|
-
|
43
|
+
associations[name.to_sym] = options
|
44
44
|
|
45
45
|
generated_methods.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
46
46
|
def #{name} # def companies
|
47
|
-
|
47
|
+
associations = self.class.associations[:#{name}] # associations = self.class.associations[:companies]
|
48
48
|
#
|
49
|
-
ResourceCollection.new(payload[:#{name}],
|
50
|
-
end #
|
49
|
+
ResourceCollection.new(payload[:#{name}], associations, self, config) # ResourceCollection.new(payload[:companies], associations, self, config)
|
50
|
+
end # end
|
51
51
|
RUBY
|
52
52
|
end
|
53
53
|
|
@@ -58,13 +58,14 @@ module Userlist
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
-
attr_reader :payload, :config
|
61
|
+
attr_reader :payload, :config, :context
|
62
62
|
|
63
63
|
def initialize(payload = {}, config = Userlist.config)
|
64
64
|
raise Userlist::ArgumentError, 'Missing required payload' unless payload
|
65
65
|
|
66
66
|
@payload = payload
|
67
67
|
@config = config
|
68
|
+
@context = :push
|
68
69
|
end
|
69
70
|
|
70
71
|
def respond_to_missing?(method, include_private = false)
|
@@ -73,7 +74,7 @@ module Userlist
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def to_hash
|
76
|
-
Serializer.serialize(self)
|
77
|
+
Serializer.serialize(self, context: context)
|
77
78
|
end
|
78
79
|
alias to_h to_hash
|
79
80
|
|
@@ -95,17 +96,23 @@ module Userlist
|
|
95
96
|
alias == eql?
|
96
97
|
|
97
98
|
def attribute_names
|
98
|
-
payload.keys.map(&:to_sym) -
|
99
|
+
payload.keys.map(&:to_sym) - association_names
|
99
100
|
end
|
100
101
|
|
101
|
-
def
|
102
|
-
self.class.
|
102
|
+
def association_names
|
103
|
+
self.class.association_names.to_a
|
103
104
|
end
|
104
105
|
|
105
106
|
def push?
|
106
107
|
true
|
107
108
|
end
|
108
109
|
|
110
|
+
def for_context(context)
|
111
|
+
dup.tap do |instance|
|
112
|
+
instance.instance_variable_set(:@context, context)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
109
116
|
private
|
110
117
|
|
111
118
|
def method_missing(method, *args, &block)
|
@@ -3,8 +3,14 @@ require 'set'
|
|
3
3
|
module Userlist
|
4
4
|
class Push
|
5
5
|
class Serializer
|
6
|
-
def self.serialize(resource)
|
7
|
-
new.serialize(resource)
|
6
|
+
def self.serialize(resource, **options)
|
7
|
+
new(**options).serialize(resource)
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :context
|
11
|
+
|
12
|
+
def initialize(context:)
|
13
|
+
@context = context
|
8
14
|
end
|
9
15
|
|
10
16
|
def serialize(resource)
|
@@ -12,6 +18,13 @@ module Userlist
|
|
12
18
|
resource
|
13
19
|
end
|
14
20
|
|
21
|
+
def serialize?(resource)
|
22
|
+
method_name = "#{context}?"
|
23
|
+
|
24
|
+
resource.respond_to?(method_name) &&
|
25
|
+
resource.public_send(method_name)
|
26
|
+
end
|
27
|
+
|
15
28
|
private
|
16
29
|
|
17
30
|
def serialize_resource(resource)
|
@@ -19,7 +32,7 @@ module Userlist
|
|
19
32
|
|
20
33
|
serialized_resources << resource
|
21
34
|
|
22
|
-
return unless resource
|
35
|
+
return unless serialize?(resource)
|
23
36
|
|
24
37
|
serialized = {}
|
25
38
|
|
@@ -27,8 +40,8 @@ module Userlist
|
|
27
40
|
serialized[name] = resource.send(name)
|
28
41
|
end
|
29
42
|
|
30
|
-
resource.
|
31
|
-
next unless result =
|
43
|
+
resource.association_names.each do |name|
|
44
|
+
next unless result = serialize_association(resource.send(name))
|
32
45
|
|
33
46
|
serialized[name] = result
|
34
47
|
end
|
@@ -36,22 +49,22 @@ module Userlist
|
|
36
49
|
serialized
|
37
50
|
end
|
38
51
|
|
39
|
-
def
|
40
|
-
return unless
|
52
|
+
def serialize_association(association)
|
53
|
+
return unless association
|
41
54
|
|
42
|
-
case
|
55
|
+
case association
|
43
56
|
when Userlist::Push::ResourceCollection
|
44
|
-
serialize_collection(
|
57
|
+
serialize_collection(association)
|
45
58
|
when Userlist::Push::Resource
|
46
|
-
serialize_resource(
|
59
|
+
serialize_resource(association)
|
47
60
|
else
|
48
|
-
raise "Cannot serialize
|
61
|
+
raise "Cannot serialize association type: #{association.class}"
|
49
62
|
end
|
50
63
|
end
|
51
64
|
|
52
65
|
def serialize_collection(collection)
|
53
66
|
serialized = collection
|
54
|
-
.map(&method(:
|
67
|
+
.map(&method(:serialize_association))
|
55
68
|
.compact
|
56
69
|
.reject(&:empty?)
|
57
70
|
|
@@ -18,14 +18,12 @@ module Userlist
|
|
18
18
|
logger.info 'Starting worker thread...'
|
19
19
|
|
20
20
|
loop do
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
logger.error "Failed to deliver payload: [#{e.class.name}] #{e.message}"
|
28
|
-
end
|
21
|
+
method, *args = *queue.pop
|
22
|
+
break if method == :stop
|
23
|
+
|
24
|
+
retryable.attempt { client.public_send(method, *args) }
|
25
|
+
rescue StandardError => e
|
26
|
+
logger.error "Failed to deliver payload: [#{e.class.name}] #{e.message}"
|
29
27
|
end
|
30
28
|
|
31
29
|
logger.info "Worker thread exited with #{queue.size} tasks still in the queue..."
|
data/lib/userlist/push/user.rb
CHANGED
data/lib/userlist/push.rb
CHANGED
@@ -5,7 +5,7 @@ require 'userlist/push/resource'
|
|
5
5
|
require 'userlist/push/resource_collection'
|
6
6
|
require 'userlist/push/relation'
|
7
7
|
|
8
|
-
require 'userlist/push/operations/
|
8
|
+
require 'userlist/push/operations/push'
|
9
9
|
require 'userlist/push/operations/delete'
|
10
10
|
|
11
11
|
require 'userlist/push/user'
|
@@ -38,39 +38,39 @@ module Userlist
|
|
38
38
|
attr_reader :config, :strategy
|
39
39
|
|
40
40
|
def events
|
41
|
-
@events ||= Relation.new(self, Event, [Operations::
|
41
|
+
@events ||= Relation.new(self, Event, [Operations::Push])
|
42
42
|
end
|
43
43
|
|
44
44
|
def users
|
45
|
-
@users ||= Relation.new(self, User, [Operations::
|
45
|
+
@users ||= Relation.new(self, User, [Operations::Push, Operations::Delete])
|
46
46
|
end
|
47
47
|
|
48
48
|
def companies
|
49
|
-
@companies ||= Relation.new(self, Company, [Operations::
|
49
|
+
@companies ||= Relation.new(self, Company, [Operations::Push, Operations::Delete])
|
50
50
|
end
|
51
51
|
|
52
52
|
def relationships
|
53
|
-
@relationships ||= Relation.new(self, Relationship, [Operations::
|
53
|
+
@relationships ||= Relation.new(self, Relationship, [Operations::Push, Operations::Delete])
|
54
54
|
end
|
55
55
|
|
56
56
|
def messages
|
57
|
-
@messages ||= Relation.new(self, Message, [Operations::
|
57
|
+
@messages ||= Relation.new(self, Message, [Operations::Push])
|
58
58
|
end
|
59
59
|
|
60
60
|
def event(payload = {})
|
61
|
-
events.
|
61
|
+
events.push(payload)
|
62
62
|
end
|
63
63
|
|
64
64
|
def user(payload = {})
|
65
|
-
users.
|
65
|
+
users.push(payload)
|
66
66
|
end
|
67
67
|
|
68
68
|
def company(payload = {})
|
69
|
-
companies.
|
69
|
+
companies.push(payload)
|
70
70
|
end
|
71
71
|
|
72
72
|
def message(payload = {})
|
73
|
-
messages.
|
73
|
+
messages.push(payload)
|
74
74
|
end
|
75
75
|
|
76
76
|
alias track event
|
data/lib/userlist/retryable.rb
CHANGED
@@ -33,17 +33,15 @@ module Userlist
|
|
33
33
|
|
34
34
|
def attempt
|
35
35
|
(0..@retries).each do |attempt|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
sleep(milliseconds / 1000.0)
|
41
|
-
end
|
42
|
-
|
43
|
-
return yield
|
44
|
-
rescue Userlist::Error => e
|
45
|
-
raise e unless retry?(e)
|
36
|
+
if attempt.positive?
|
37
|
+
milliseconds = delay(attempt)
|
38
|
+
logger.debug "Retrying in #{milliseconds}ms, #{@retries - attempt} retries left"
|
39
|
+
sleep(milliseconds / 1000.0)
|
46
40
|
end
|
41
|
+
|
42
|
+
return yield
|
43
|
+
rescue Userlist::Error => e
|
44
|
+
raise e unless retry?(e)
|
47
45
|
end
|
48
46
|
|
49
47
|
logger.debug 'Retries exhausted, giving up'
|
data/lib/userlist/version.rb
CHANGED
data/userlist.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ['benedikt@userlist.com']
|
10
10
|
|
11
11
|
spec.summary = 'Ruby wrapper for the Userlist API'
|
12
|
-
spec.homepage = 'http://github.com/
|
12
|
+
spec.homepage = 'http://github.com/userlist/userlist-ruby'
|
13
13
|
spec.license = 'MIT'
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
@@ -19,13 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
-
spec.required_ruby_version = '>=
|
23
|
-
|
24
|
-
spec.add_development_dependency 'bundler', '>= 1.15'
|
25
|
-
spec.add_development_dependency 'jwt', '~> 2.2'
|
26
|
-
spec.add_development_dependency 'rake', '~> 13.0'
|
27
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
28
|
-
spec.add_development_dependency 'webmock', '~> 3.18'
|
22
|
+
spec.required_ruby_version = '>= 3.0'
|
29
23
|
|
30
24
|
spec.metadata = { 'rubygems_mfa_required' => 'true' }
|
31
25
|
end
|
metadata
CHANGED
@@ -1,84 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: userlist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benedikt Deicke
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
11
|
-
dependencies:
|
12
|
-
- !ruby/object:Gem::Dependency
|
13
|
-
name: bundler
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
15
|
-
requirements:
|
16
|
-
- - ">="
|
17
|
-
- !ruby/object:Gem::Version
|
18
|
-
version: '1.15'
|
19
|
-
type: :development
|
20
|
-
prerelease: false
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
-
requirements:
|
23
|
-
- - ">="
|
24
|
-
- !ruby/object:Gem::Version
|
25
|
-
version: '1.15'
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: jwt
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
29
|
-
requirements:
|
30
|
-
- - "~>"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '2.2'
|
33
|
-
type: :development
|
34
|
-
prerelease: false
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
-
requirements:
|
37
|
-
- - "~>"
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '2.2'
|
40
|
-
- !ruby/object:Gem::Dependency
|
41
|
-
name: rake
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - "~>"
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '13.0'
|
47
|
-
type: :development
|
48
|
-
prerelease: false
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - "~>"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '13.0'
|
54
|
-
- !ruby/object:Gem::Dependency
|
55
|
-
name: rspec
|
56
|
-
requirement: !ruby/object:Gem::Requirement
|
57
|
-
requirements:
|
58
|
-
- - "~>"
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version: '3.0'
|
61
|
-
type: :development
|
62
|
-
prerelease: false
|
63
|
-
version_requirements: !ruby/object:Gem::Requirement
|
64
|
-
requirements:
|
65
|
-
- - "~>"
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '3.0'
|
68
|
-
- !ruby/object:Gem::Dependency
|
69
|
-
name: webmock
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
71
|
-
requirements:
|
72
|
-
- - "~>"
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
version: '3.18'
|
75
|
-
type: :development
|
76
|
-
prerelease: false
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
78
|
-
requirements:
|
79
|
-
- - "~>"
|
80
|
-
- !ruby/object:Gem::Version
|
81
|
-
version: '3.18'
|
10
|
+
date: 2025-10-17 00:00:00.000000000 Z
|
11
|
+
dependencies: []
|
82
12
|
email:
|
83
13
|
- benedikt@userlist.com
|
84
14
|
executables: []
|
@@ -107,8 +37,8 @@ files:
|
|
107
37
|
- lib/userlist/push/company.rb
|
108
38
|
- lib/userlist/push/event.rb
|
109
39
|
- lib/userlist/push/message.rb
|
110
|
-
- lib/userlist/push/operations/create.rb
|
111
40
|
- lib/userlist/push/operations/delete.rb
|
41
|
+
- lib/userlist/push/operations/push.rb
|
112
42
|
- lib/userlist/push/relation.rb
|
113
43
|
- lib/userlist/push/relationship.rb
|
114
44
|
- lib/userlist/push/resource.rb
|
@@ -128,7 +58,7 @@ files:
|
|
128
58
|
- lib/userlist/token.rb
|
129
59
|
- lib/userlist/version.rb
|
130
60
|
- userlist.gemspec
|
131
|
-
homepage: http://github.com/
|
61
|
+
homepage: http://github.com/userlist/userlist-ruby
|
132
62
|
licenses:
|
133
63
|
- MIT
|
134
64
|
metadata:
|
@@ -140,7 +70,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
140
70
|
requirements:
|
141
71
|
- - ">="
|
142
72
|
- !ruby/object:Gem::Version
|
143
|
-
version: '
|
73
|
+
version: '3.0'
|
144
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
75
|
requirements:
|
146
76
|
- - ">="
|