sunstone 5.1.0.4 → 5.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +5 -13
  3. data/ext/active_record/associations.rb +2 -7
  4. data/ext/active_record/associations/collection_association.rb +25 -18
  5. data/ext/active_record/attribute_methods.rb +19 -35
  6. data/ext/active_record/finder_methods.rb +138 -90
  7. data/ext/active_record/persistence.rb +16 -11
  8. data/ext/active_record/relation.rb +7 -47
  9. data/ext/active_record/relation/calculations.rb +5 -3
  10. data/ext/active_record/relation/query_methods.rb +9 -0
  11. data/ext/active_record/statement_cache.rb +4 -6
  12. data/ext/active_record/transactions.rb +9 -19
  13. data/ext/arel/nodes/select_statement.rb +26 -12
  14. data/lib/active_record/connection_adapters/sunstone/database_statements.rb +76 -25
  15. data/lib/active_record/connection_adapters/sunstone/type/json.rb +1 -1
  16. data/lib/active_record/connection_adapters/sunstone_adapter.rb +2 -3
  17. data/lib/arel/collectors/sunstone.rb +21 -19
  18. data/lib/arel/visitors/sunstone.rb +4 -8
  19. data/lib/sunstone.rb +2 -3
  20. data/lib/sunstone/connection.rb +2 -2
  21. data/lib/sunstone/exception.rb +8 -1
  22. data/lib/sunstone/version.rb +1 -1
  23. data/sunstone.gemspec +3 -3
  24. data/test/active_record/associations/has_many_test.rb +30 -2
  25. data/test/active_record/eager_loading_test.rb +10 -0
  26. data/test/active_record/persistance_test.rb +7 -7
  27. data/test/active_record/query/count_test.rb +13 -0
  28. data/test/active_record/query_test.rb +6 -6
  29. data/test/sunstone/connection/send_request_test.rb +1 -1
  30. data/test/test_helper.rb +1 -1
  31. metadata +9 -10
  32. data/ext/active_record/associations/association.rb +0 -16
  33. data/ext/active_record/batches.rb +0 -12
@@ -1,7 +1,7 @@
1
1
  module Arel
2
2
  module Collectors
3
3
  class Sunstone < Arel::Collectors::Bind
4
-
4
+
5
5
  MAX_URI_LENGTH = 2083
6
6
 
7
7
  attr_accessor :request_type, :table, :where, :limit, :offset, :order, :operation, :columns, :updates, :eager_loads, :id, :distinct, :distinct_on
@@ -9,24 +9,23 @@ module Arel
9
9
  # This is used to removed an bind values. It is not used in the request
10
10
  attr_accessor :join_source
11
11
 
12
+ attr_reader :binds
13
+
12
14
  def initialize
13
15
  @join_source = []
14
- super
16
+ @binds = []
15
17
  end
16
-
17
- def cast_attribute(v)
18
- if (v.is_a?(ActiveRecord::Attribute))
19
- v.value_for_database
20
- else
21
- v
22
- end
18
+
19
+ def add_bind(bind)
20
+ @binds << bind.value_for_database
21
+ bind
23
22
  end
24
23
 
25
24
  def substitute_binds hash, bvs
26
25
  if hash.is_a?(Array)
27
26
  hash.map do |v|
28
27
  if v.is_a?(Arel::Nodes::BindParam)
29
- cast_attribute(bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
28
+ bvs.shift#.value_for_database
30
29
  elsif v.is_a?(Hash) || v.is_a?(Array)
31
30
  substitute_binds(v, bvs)
32
31
  else
@@ -37,7 +36,7 @@ module Arel
37
36
  newhash = {}
38
37
  hash.each do |k, v|
39
38
  if v.is_a?(Arel::Nodes::BindParam)
40
- newhash[k] = cast_attribute(bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
39
+ newhash[k] = bvs.shift || v.value.value_for_database
41
40
  elsif v.is_a?(Hash)
42
41
  newhash[k] = substitute_binds(v, bvs)
43
42
  elsif v.is_a?(Array)
@@ -48,16 +47,12 @@ module Arel
48
47
  end
49
48
  newhash
50
49
  elsif hash.is_a?(Arel::Nodes::BindParam)
51
- cast_attribute(bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
50
+ bvs.shift || hash.value.value_for_database
52
51
  else
53
- cast_attribute(bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
52
+ bvs.shift || hash.value.value_for_database
54
53
  end
55
54
  end
56
55
 
57
- def value
58
- flatten_nested(where).flatten
59
- end
60
-
61
56
  def flatten_nested(obj)
62
57
  if obj.is_a?(Array)
63
58
  obj.map { |w| flatten_nested(w) }
@@ -68,6 +63,13 @@ module Arel
68
63
  end
69
64
  end
70
65
 
66
+ def value
67
+ self
68
+ end
69
+
70
+ def sql_for(bvs, conn = nil)
71
+ compile(bvs, conn)
72
+ end
71
73
  def compile bvs, conn = nil
72
74
  path = "/#{table}"
73
75
  headers = {}
@@ -110,7 +112,7 @@ module Arel
110
112
  elsif offset
111
113
  params[:offset] = offset
112
114
  end
113
-
115
+
114
116
  case operation
115
117
  when :count
116
118
  path += "/#{operation}"
@@ -121,7 +123,7 @@ module Arel
121
123
  path += "/#{params[:where]['id']}"
122
124
  params.delete(:where)
123
125
  end
124
-
126
+
125
127
  if params.size > 0 && request_type == Net::HTTP::Get
126
128
  newpath = path + "?#{CGI.escape(MessagePack.pack(params))}"
127
129
  if newpath.length > MAX_URI_LENGTH
@@ -10,10 +10,6 @@ module Arel
10
10
  module Visitors
11
11
  class Sunstone < Arel::Visitors::Reduce
12
12
 
13
- def initialize
14
- @dispatch = get_dispatch_cache
15
- end
16
-
17
13
  def compile node, &block
18
14
  accept(node, Arel::Collectors::SQLString.new, &block).value
19
15
  end
@@ -81,7 +77,6 @@ module Arel
81
77
  collector.operation = :insert
82
78
 
83
79
  if o.values
84
-
85
80
  if o.values.is_a?(Arel::Nodes::SqlLiteral) && o.values == 'DEFAULT VALUES'
86
81
  collector.updates = {}
87
82
  else
@@ -108,7 +103,7 @@ module Arel
108
103
  end
109
104
  }
110
105
  else
111
- collector.updates[k] = values[i]
106
+ collector.updates[k] = visit(values[i], collector)
112
107
  end
113
108
  end
114
109
  end
@@ -818,7 +813,7 @@ module Arel
818
813
  def visit_Arel_Nodes_Equality o, collector
819
814
  key = visit(o.left, collector)
820
815
  value = (o.right.nil? ? nil : visit(o.right, collector))
821
-
816
+
822
817
  if key.is_a?(Hash)
823
818
  add_to_bottom_of_hash(key, {eq: value})
824
819
  elsif o.left.class.name == 'Arel::Attributes::Key'
@@ -948,7 +943,8 @@ module Arel
948
943
  alias :visit_Arel_Attributes_Boolean :visit_Arel_Attributes_Attribute
949
944
 
950
945
  def visit_Arel_Nodes_BindParam o, collector
951
- o
946
+ a = collector.add_bind(o.value)
947
+ o.is_a?(Arel::Nodes::BindParam) ? o : a
952
948
  end
953
949
 
954
950
  def literal(o, collector)
@@ -24,11 +24,11 @@ require File.expand_path(File.join(__FILE__, '../../ext/active_record/statement_
24
24
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/associations'))
25
25
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/relation'))
26
26
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/relation/calculations'))
27
+ require File.expand_path(File.join(__FILE__, '../../ext/active_record/relation/query_methods'))
27
28
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/persistence'))
28
29
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/callbacks'))
29
30
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/attribute_methods'))
30
31
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/transactions'))
31
- require File.expand_path(File.join(__FILE__, '../../ext/active_record/associations/association'))
32
32
  require File.expand_path(File.join(__FILE__, '../../ext/active_record/associations/collection_association'))
33
33
 
34
34
  require File.expand_path(File.join(__FILE__, '../../ext/active_support/core_ext/object/to_query'))
@@ -38,5 +38,4 @@ require File.expand_path(File.join(__FILE__, '../../ext/arel/nodes/eager_load'))
38
38
  require File.expand_path(File.join(__FILE__, '../../ext/arel/attributes/relation'))
39
39
  require File.expand_path(File.join(__FILE__, '../../ext/arel/attributes/empty_relation'))
40
40
  require File.expand_path(File.join(__FILE__, '../../ext/arel/nodes/select_statement'))
41
- require File.expand_path(File.join(__FILE__, '../../ext/active_record/finder_methods'))
42
- require File.expand_path(File.join(__FILE__, '../../ext/active_record/batches'))
41
+ require File.expand_path(File.join(__FILE__, '../../ext/active_record/finder_methods'))
@@ -397,8 +397,8 @@ module Sunstone
397
397
  raise Sunstone::Exception::MovedPermanently, response.body
398
398
  when 502
399
399
  raise ActiveRecord::ConnectionNotEstablished, response.body
400
- when 300..599
401
- raise Sunstone::Exception, response.body
400
+ when 500..599
401
+ raise Sunstone::ServerError, response.body
402
402
  else
403
403
  raise Sunstone::Exception, response.body
404
404
  end
@@ -1,6 +1,13 @@
1
1
  module Sunstone
2
2
 
3
- class Exception < ::Exception
3
+ class ServerError < ::RuntimeError
4
+ end
5
+
6
+ # RuntimeErrors don't get translated by Rails into
7
+ # ActiveRecord::StatementInvalid which StandardError do. Would rather
8
+ # use StandardError, but it's usefull with Sunstone to know when something
9
+ # raises a Sunstone::Exception::NotFound or Forbidden
10
+ class Exception < ::RuntimeError
4
11
 
5
12
  class UnexpectedResponse < Sunstone::Exception
6
13
  end
@@ -1,3 +1,3 @@
1
1
  module Sunstone
2
- VERSION = '5.1.0.4'
2
+ VERSION = '5.2.1'
3
3
  end
@@ -23,16 +23,16 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'minitest-reporters'
24
24
  s.add_development_dependency 'mocha'
25
25
  s.add_development_dependency 'faker'
26
- s.add_development_dependency 'factory_girl'
26
+ s.add_development_dependency 'factory_bot'
27
27
  s.add_development_dependency 'webmock'
28
28
  #s.add_development_dependency 'sdoc-templates-42floors'
29
29
  s.add_development_dependency 'rgeo'
30
30
  s.add_development_dependency 'simplecov'
31
31
  s.add_development_dependency 'byebug'
32
- s.add_development_dependency 'activesupport', '~> 5.1.0'
32
+ s.add_development_dependency 'activesupport', '~> 5.2.1'
33
33
 
34
34
  # Runtime
35
35
  s.add_runtime_dependency 'msgpack'
36
36
  s.add_runtime_dependency 'cookie_store'
37
- s.add_runtime_dependency 'activerecord', '~> 5.1.0'
37
+ s.add_runtime_dependency 'activerecord', '~> 5.2.1'
38
38
  end
@@ -116,7 +116,6 @@ class ActiveRecord::Associations::HasManyTest < ActiveSupport::TestCase
116
116
  }.to_json
117
117
  )
118
118
 
119
- # fleet.ships = [ship]
120
119
  fleet = Fleet.eager_load(:ships).find(1)
121
120
  assert fleet.update(ships: [Ship.new(name: 'Voyager')])
122
121
  assert_equal 1, fleet.id
@@ -150,7 +149,6 @@ class ActiveRecord::Associations::HasManyTest < ActiveSupport::TestCase
150
149
  }.to_json
151
150
  )
152
151
 
153
- # fleet.ships = [ship]
154
152
  fleet = Fleet.eager_load(:ships).find(1)
155
153
  fleet.ships.first.name = 'Voyager'
156
154
  fleet.save
@@ -187,6 +185,36 @@ class ActiveRecord::Associations::HasManyTest < ActiveSupport::TestCase
187
185
  assert_requested req_stub
188
186
  end
189
187
 
188
+ test '#update persisted record doesnt include any unchanged associations' do
189
+ webmock(:get, '/fleets', where: {id: 1}, limit: 1, include: [:ships]).to_return({
190
+ body: [{
191
+ id: 1,
192
+ name: 'Armada Trio',
193
+ ships: [
194
+ {id: 2, fleet_id: 1, name: 'Definant'}, {id: 3, fleet_id: 1, name: 'Enterprise'}
195
+ ]
196
+ }].to_json
197
+ })
198
+
199
+ req_stub = webmock(:patch, '/fleets/1').with(
200
+ body: { fleet: { name: 'New NAME!!' } }.to_json
201
+ ).to_return(
202
+ body: {
203
+ id: 1,
204
+ name: 'New NAME!!'
205
+ }.to_json
206
+ )
207
+
208
+ # fleet.ships = [ship]
209
+ fleet = Fleet.eager_load(:ships).find(1)
210
+ assert fleet.ships.loaded?
211
+ #[{id: 2, fleet_id: 1, name: 'Definant'}, {id: 3, fleet_id: 1, name: 'Enterprise'}]
212
+ fleet.update(name: 'New NAME!!', ships: fleet.ships)
213
+ fleet.save
214
+
215
+ assert_requested req_stub
216
+ end
217
+
190
218
  # Clearing the relationship =================================================
191
219
 
192
220
  test '#update clears has_many relationship' do
@@ -47,4 +47,14 @@ class ActiveRecord::EagerLoadingTest < ActiveSupport::TestCase
47
47
  assert_equal [1], fleets.first.ships.map(&:id)
48
48
  end
49
49
 
50
+
51
+ test '#eager_loads' do
52
+ webmock(:get, "/fleets", include: [{:ships => :sailors}]).to_return(body: [{
53
+ id: 1, ships: [{id: 1, fleet_id: 1}]
54
+ }].to_json)
55
+
56
+ fleets = Fleet.eager_load(:ships, :sailors).limit(2).to_sql
57
+ assert_equal '', fleets
58
+ end
59
+
50
60
  end
@@ -45,7 +45,7 @@ class ActiveRecord::PersistanceTest < ActiveSupport::TestCase
45
45
  TestModelA.create
46
46
  end
47
47
  end
48
-
48
+
49
49
  test '#create with errors' do
50
50
  req_stub = webmock(:post, "/fleets").with(
51
51
  body: { fleet: {} }.to_json
@@ -78,7 +78,7 @@ class ActiveRecord::PersistanceTest < ActiveSupport::TestCase
78
78
 
79
79
  fleet = Fleet.find(1)
80
80
  fleet.save
81
-
81
+
82
82
  assert fleet.save
83
83
  assert_equal 1, fleet.id
84
84
  assert_equal 'Armada Duo', fleet.name
@@ -108,9 +108,9 @@ class ActiveRecord::PersistanceTest < ActiveSupport::TestCase
108
108
  TestModelB.create
109
109
  end
110
110
  end
111
-
112
-
113
-
111
+
112
+
113
+
114
114
  test '#update clears belongs_to relationship' do
115
115
  webmock(:get, "/ships", where: {id: 1}, limit: 1).to_return(
116
116
  body: [{id: 1, fleet_id: 1, name: 'Armada Uno'}].to_json
@@ -125,7 +125,7 @@ class ActiveRecord::PersistanceTest < ActiveSupport::TestCase
125
125
  assert ship.update(fleet: nil)
126
126
  assert_requested req_stub
127
127
  end
128
-
128
+
129
129
  test '#update' do
130
130
  webmock(:get, "/ships", where: {id: 1}, limit: 1).to_return(
131
131
  body: [{id: 1, fleet_id: nil, name: 'Armada Uno'}].to_json
@@ -140,7 +140,7 @@ class ActiveRecord::PersistanceTest < ActiveSupport::TestCase
140
140
 
141
141
  assert_requested req_stub
142
142
  end
143
-
143
+
144
144
  test '#update!' do
145
145
  webmock(:get, "/ships", where: {id: 1}, limit: 1).to_return(
146
146
  body: [{id: 1, fleet_id: nil, name: 'Armada Uno'}].to_json
@@ -8,7 +8,12 @@ class ActiveRecord::QueryCountTest < ActiveSupport::TestCase
8
8
  end
9
9
  end
10
10
 
11
+ class Fleet < ActiveRecord::Base
12
+ has_many :ships
13
+ end
14
+
11
15
  class Ship < ActiveRecord::Base
16
+ belongs_to :fleet
12
17
  end
13
18
 
14
19
  test '::count' do
@@ -27,6 +32,14 @@ class ActiveRecord::QueryCountTest < ActiveSupport::TestCase
27
32
  assert_equal 10, Ship.count(:id)
28
33
  end
29
34
 
35
+ test '::count with eager_load' do
36
+ webmock(:get, "/ships/calculate", select: [{count: "id"}], limit: 100, offset: 0).to_return({
37
+ body: [10].to_json
38
+ })
39
+
40
+ assert_equal 10, Ship.eager_load(:fleet).count
41
+ end
42
+
30
43
  test '::sum(:column)' do
31
44
  webmock(:get, "/ships/calculate", select: [{sum: "weight"}], limit: 100, offset: 0).to_return({
32
45
  body: [10].to_json
@@ -28,7 +28,7 @@ class ActiveRecord::QueryTest < ActiveSupport::TestCase
28
28
 
29
29
  assert_nil Ship.first
30
30
  end
31
-
31
+
32
32
  test '::first!' do
33
33
  webmock(:get, "/ships", { limit: 1, order: [{id: :asc}] }).to_return({
34
34
  body: [].to_json
@@ -46,23 +46,23 @@ class ActiveRecord::QueryTest < ActiveSupport::TestCase
46
46
 
47
47
  assert_nil Ship.last
48
48
  end
49
-
49
+
50
50
  test '::where on the same column multiple times with symbols and strings' do
51
51
  webmock(:get, "/ships", { where: [{ id: {gt: 10} }, 'AND', {id: {gt: 11}}], limit: 100, offset: 0 }).to_return(body: [].to_json)
52
52
 
53
53
  arel_table = Ship.arel_table
54
54
  assert_equal [], Ship.where(arel_table[:id].gt(10)).where(arel_table['id'].gt(11)).to_a
55
55
  end
56
-
56
+
57
57
  test '::where(AND CONDITION)' do
58
58
  webmock(:get, "/ships", { where: {id: 10, name: 'name'}, limit: 1, order: [{id: :asc}] }).to_return({
59
59
  body: [{id: 42}].to_json
60
60
  })
61
-
61
+
62
62
  arel_table = Ship.arel_table
63
63
  assert_equal 42, Ship.where(arel_table[:id].eq(10).and(arel_table[:name].eq('name'))).first.id
64
64
  end
65
-
65
+
66
66
  test '::where(OR CONDITION)' do
67
67
  webmock(:get, "/ships", { where: [{id: 10}, 'OR', {name: 'name'}], limit: 1, order: [{id: :asc}] }).to_return({
68
68
  body: [{id: 42}].to_json
@@ -90,7 +90,7 @@ class ActiveRecord::QueryTest < ActiveSupport::TestCase
90
90
 
91
91
  assert_equal 42, Ship.where(name: name)[0].id
92
92
  end
93
-
93
+
94
94
  test '::where with JOIN' do
95
95
  webmock(:get, "/ships", {where: { ownerships: {id: {eq: 1}} }, limit: 100, offset: 0 }).to_return({
96
96
  body: [{id: 42}].to_json
@@ -89,7 +89,7 @@ class Sunstone::Connection::SendRequestTest < ActiveSupport::TestCase
89
89
  assert_raises(Sunstone::Exception::ApiVersionUnsupported) { connection.send_request(Net::HTTP::Get.new('/422')) }
90
90
  assert_raises(Sunstone::Exception) { connection.send_request(Net::HTTP::Get.new('/450')) }
91
91
  assert_raises(Sunstone::Exception::ServiceUnavailable) { connection.send_request(Net::HTTP::Get.new('/503')) }
92
- assert_raises(Sunstone::Exception) { connection.send_request(Net::HTTP::Get.new('/550')) }
92
+ assert_raises(Sunstone::ServerError) { connection.send_request(Net::HTTP::Get.new('/550')) }
93
93
  end
94
94
 
95
95
  test '#send_request(#<Net::HTTPRequest>, &block) returns value returned from &block' do
@@ -14,7 +14,7 @@ require "minitest/autorun"
14
14
  require 'minitest/unit'
15
15
  require 'minitest/reporters'
16
16
  require 'webmock/minitest'
17
- require 'mocha/mini_test'
17
+ require 'mocha/minitest'
18
18
 
19
19
  require 'sunstone'
20
20
  require File.expand_path('../schema_mock.rb', __FILE__)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunstone
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.0.4
4
+ version: 5.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-08 00:00:00.000000000 Z
11
+ date: 2018-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -109,7 +109,7 @@ dependencies:
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
- name: factory_girl
112
+ name: factory_bot
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - ">="
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: 5.1.0
187
+ version: 5.2.1
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: 5.1.0
194
+ version: 5.2.1
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: msgpack
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -226,14 +226,14 @@ dependencies:
226
226
  requirements:
227
227
  - - "~>"
228
228
  - !ruby/object:Gem::Version
229
- version: 5.1.0
229
+ version: 5.2.1
230
230
  type: :runtime
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
233
233
  requirements:
234
234
  - - "~>"
235
235
  - !ruby/object:Gem::Version
236
- version: 5.1.0
236
+ version: 5.2.1
237
237
  description: A library for interacting with REST APIs. Similar to ActiveResource
238
238
  email:
239
239
  - jonbracy@gmail.com
@@ -250,15 +250,14 @@ files:
250
250
  - Rakefile
251
251
  - TODO.md
252
252
  - ext/active_record/associations.rb
253
- - ext/active_record/associations/association.rb
254
253
  - ext/active_record/associations/collection_association.rb
255
254
  - ext/active_record/attribute_methods.rb
256
- - ext/active_record/batches.rb
257
255
  - ext/active_record/callbacks.rb
258
256
  - ext/active_record/finder_methods.rb
259
257
  - ext/active_record/persistence.rb
260
258
  - ext/active_record/relation.rb
261
259
  - ext/active_record/relation/calculations.rb
260
+ - ext/active_record/relation/query_methods.rb
262
261
  - ext/active_record/statement_cache.rb
263
262
  - ext/active_record/transactions.rb
264
263
  - ext/active_support/core_ext/object/to_query.rb
@@ -326,7 +325,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
326
325
  version: '0'
327
326
  requirements: []
328
327
  rubyforge_project:
329
- rubygems_version: 2.6.11
328
+ rubygems_version: 2.7.4
330
329
  signing_key:
331
330
  specification_version: 4
332
331
  summary: A library for interacting with REST APIs