gecko-ruby 0.2.6 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20b88c9b40a367779ee76883eb9c6311b9bddaf4520895d6385f4e2628413919
4
- data.tar.gz: 1acf395ece0f1abbfd475f976667658894d0b56bdebd461371e25825e92e75b4
3
+ metadata.gz: df8f73db1e7b003d6bb6390cbf04bca52b59700ef2d9664e6015974c4306bccf
4
+ data.tar.gz: 74ac60ce61a2baf83ef5dbba6bdb813c8c117aa83729430e8da5be1befc0e94a
5
5
  SHA512:
6
- metadata.gz: 27433416b6b19c2c2678da35bfc9c4ce0ed6f6f81866bf4e8993b26cb1430eb8691270810796014cd53558de573cbca59ebdd1bfea1291e82e1bfec8fc1794ec
7
- data.tar.gz: 32f3d00580a3f09a288938a6675fd1c94580e5e15e00956bd861841103ac5842d56926e3867bd935e9cd2e0675b3537d916bcf0589ba589c780c1e98555f58b0
6
+ metadata.gz: f0e27ab4669777a3641565962b146f7fd71e6e74e3c46b6180708b79d0478893ced8fb2a37f6aed308244968cee4998195d503fe1f0847c68f5cfffe975a701c
7
+ data.tar.gz: d7bea6254cb350fd0a770346778cf97c999baecc8d18ac75c349e81423db88ee14c3e5f49919ba6d287f3c7f9e9cc600b518f8ac18f3dcf420342370ef91e876
@@ -64,3 +64,6 @@ Layout/MultilineOperationIndentation:
64
64
 
65
65
  Style/ClassAndModuleChildren:
66
66
  EnforcedStyle: compact
67
+
68
+ Style/DoubleNegation:
69
+ Enabled: false
@@ -2,8 +2,9 @@ language: ruby
2
2
  before_install:
3
3
  - gem install bundler
4
4
  rvm:
5
- - 1.9.3
6
- - 2.0
7
5
  - 2.1
8
6
  - 2.2
9
7
  - 2.3
8
+ - 2.4
9
+ - 2.5
10
+ - ruby-head
@@ -1,5 +1,13 @@
1
- ## 0.2.6 (2019-03-19)
2
- - [BACKPORT] Fix issue with find_many which manifested as a bug in has_many definitions with cached records being duplicated when more than 100 children existed.
1
+ ## 0.5.0 (2018-08-15)
2
+ - [BREAKING CHANGE] has_many associations now return an enumerable
3
+ `CollectionProxy` where they used to return a plain array.
4
+ - `has_many` associations now support `.build` which automatically assigns the parent
5
+ relation. `item = order.order_line_items.build(quantity: 123, variant_id: 123, price: 123)`
6
+ `item.order == order`.
7
+ - Support for embedded serialization.
8
+ i.e `order.order_line_items.build(quantity: 123, price: 123, variant_id: 123); order.save`
9
+ will now save the Order and the order line items in a single API request.
10
+ - Add minimum `oauth2` gem dependency
3
11
 
4
12
  ## 0.2.5 (2018-01-15)
5
13
  - Add `User#account_name`
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014 TradeGecko Pte Ltd.
1
+ Copyright (c) 2018 TradeGecko Pte Ltd.
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -5,7 +5,7 @@ The official TradeGecko API RubyGem
5
5
 
6
6
  This library provides a Ruby interface to publicly available (beta) API for TradeGecko.
7
7
 
8
- If you are unfamiliar with the TradeGecko API, you can read the documentation located at [http://developer.tradegecko.com](http://developer.tradegecko.com)
8
+ If you are unfamiliar with the TradeGecko API, you can read the documentation located at [https://developer.tradegecko.com](https://developer.tradegecko.com)
9
9
 
10
10
  ## Installation
11
11
 
@@ -76,6 +76,8 @@ client.Product.where(ids: [123, 124])
76
76
 
77
77
  ## Building Records
78
78
 
79
+ You can create new records by calling `build` on the appropriate adapter.
80
+
79
81
  ```ruby
80
82
  geckobot = client.Product.build(name: "Geckobot", product_type: "Robot")
81
83
  #=> <Gecko::Record::Product id=nil name="Geckobot" product_type: "Robot">
@@ -87,6 +89,8 @@ geckobot.persisted?
87
89
 
88
90
  #### Create Record
89
91
 
92
+ You can persist new records by calling `save`.
93
+
90
94
  ```ruby
91
95
  geckobot = client.Product.build(name: "Geckobot", product_type: "Robot")
92
96
  #=> <Gecko::Record::Product id=nil name="Geckobot" product_type: "Robot">
@@ -98,6 +102,19 @@ geckobot
98
102
  #=> <Gecko::Record::Product id=124 name="Geckobot" product_type: "Robot">
99
103
  ```
100
104
 
105
+ You can also create new records from inside a parent object.
106
+
107
+ ```ruby
108
+ variant = product.variants.build(name: "Geckobot", sku: "ROBO")
109
+ #=> <Gecko::Record::Variant id=nil product_id=123 name="Geckobot" sku: "ROBO">
110
+ variant.persisted?
111
+ #=> false
112
+ variant.save #=> Persists to API
113
+ #=> true
114
+ variant
115
+ #=> <Gecko::Record::Variant id=125 product_id=123 name="Geckobot" sku: "ROBO">
116
+ ```
117
+
101
118
  #### Update Record
102
119
 
103
120
  ```ruby
@@ -112,6 +129,39 @@ geckobot
112
129
  #=> <Gecko::Record::Product id=124 name="Geckobot" product_type: "Robo-boogie">
113
130
  ```
114
131
 
132
+ #### Embedded Record Serialization
133
+
134
+ Some records support being saved inside of their parents.
135
+ A good example is creating a Sales Order and it's line items.
136
+
137
+ ```ruby
138
+ order = client.Order.build(company_id: 123, shipping_address_id: 123)
139
+ order.order_line_items.build(quantity: 1, variant_id: 123, price: 10.5)
140
+ order.order_line_items.build(quantity: 2, variant_id: 124, price: 11.0)
141
+ order.save # Persists to API
142
+ #=> true
143
+ order.order_line_items
144
+ #=> [<Gecko::Record::OrderLineItem id=125 variant_id=123 quantity: 1 price: '10.5'>,
145
+ <Gecko::Record::OrderLineItem id=126 variant_id=124 quantity: 2 price: '11.0'>]
146
+ ```
147
+
148
+ This also works when adding new items to an existing order.
149
+
150
+ ```ruby
151
+ order = client.Order.find(123)
152
+ order.order_line_items.build(quantity: 1, variant_id: 123, price: 10.5)
153
+ order.order_line_items.build(quantity: 2, variant_id: 124, price: 11.0)
154
+ order.save # Persists to API
155
+ #=> true
156
+ order.order_line_items
157
+ #=> [<Gecko::Record::OrderLineItem id=125 variant_id=123 quantity: 1 price: '10.5'>,
158
+ <Gecko::Record::OrderLineItem id=126 variant_id=124 quantity: 2 price: '11.0'>]
159
+ ```
160
+
161
+ N.B. Only creation of embedded objects works at this time.
162
+ Updating/Deleting embedded items must still be done by calling `save/destroy`
163
+ on each of the child objects themselves.
164
+
115
165
  #### Validations
116
166
 
117
167
  ```ruby
@@ -162,7 +212,7 @@ client.Product.last_response.headers['X-Rate-Limit-Reset']
162
212
 
163
213
  ## Contributing
164
214
 
165
- 1. Fork it ( http://github.com/tradegecko/gecko/fork )
215
+ 1. Fork it ( https://github.com/tradegecko/gecko/fork )
166
216
  2. Create your feature branch (`git checkout -b my-new-feature`)
167
217
  3. Commit your changes (`git commit -am 'Add some feature'`)
168
218
  4. Push to the branch (`git push origin my-new-feature`)
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "thor"
30
30
  spec.add_development_dependency "pry"
31
31
 
32
- spec.add_dependency "oauth2"
32
+ spec.add_dependency "oauth2", "> 1.1.0"
33
33
  spec.add_dependency "virtus"
34
34
  spec.add_dependency "activesupport"
35
35
  end
@@ -2,67 +2,174 @@ module Gecko
2
2
  module Helpers
3
3
  # Helper for has_many/belongs_to relationships
4
4
  module AssociationHelper
5
- # Set up a belongs_to relationship between two classes based on a
6
- # JSON key of {class_name}_id.
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ # Set up a belongs_to relationship between two classes based on a
11
+ # JSON key of {class_name}_id.
12
+ #
13
+ # @example
14
+ # class Gecko::Record::Variant
15
+ # belongs_to :product
16
+ # end
17
+ #
18
+ # @param [Symbol] model_name
19
+ # @param [#to_hash] options options for setting up the relationship
20
+ # @option options [String] :class_name Override the default class name
21
+ # @option options [String] :readonly (false) Whether to serialize
22
+ # this attribute
23
+ #
24
+ # @return [undefined]
25
+ #
26
+ # @api public
27
+ def belongs_to(model_name, options={})
28
+ class_name = options[:class_name] || model_name.to_s.classify
29
+ foreign_key = model_name.to_s.foreign_key.to_sym
30
+
31
+ define_method model_name do
32
+ if (id = attributes[foreign_key])
33
+ @client.adapter_for(class_name).find(id)
34
+ end
35
+ end
36
+ attribute foreign_key, Integer, readonly: options[:readonly]
37
+ end
38
+
39
+ # Set up a has_many relationship between two classes based on a
40
+ # JSON key of {class_name}_ids.
41
+ #
42
+ # @example
43
+ # class Gecko::Record::Product
44
+ # has_many :variants
45
+ # end
46
+ #
47
+ # @param [Symbol] model_name
48
+ # @param [#to_hash] options options for setting up the relationship
49
+ # @option options [String] :class_name Override the default class name
50
+ # @option options [Boolean] :readonly (true) Whether to serialize this
51
+ # attribute
52
+ # @option options [Boolean] :embedded (false) Whether this relation should
53
+ # persisted inside it's parent record
54
+ #
55
+ # @return [undefined]
56
+ #
57
+ # @api public
58
+ def has_many(association_name, options={})
59
+ model_name = association_name.to_s.singularize
60
+ class_name = options[:class_name] || model_name.classify
61
+ foreign_key = model_name.foreign_key.pluralize.to_sym
62
+ readonly = options.key?(:readonly) ? options[:readonly] : true
63
+
64
+ define_method association_name do
65
+ collection_proxies[association_name] ||= begin
66
+ ids = self.attributes[foreign_key]
67
+ if ids.any?
68
+ collection = @client.adapter_for(class_name).find_many(ids)
69
+ else
70
+ collection = []
71
+ end
72
+
73
+ build_collection_proxy(collection, {
74
+ embedded: options[:embedded],
75
+ class_name: class_name,
76
+ association_name: association_name
77
+ })
78
+ end
79
+ end
80
+ attribute foreign_key, Array[Integer], readonly: readonly
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ # Stores a reference to all of the child collection proxies on the model
7
87
  #
8
- # @example
9
- # class Gecko::Record::Variant
10
- # belongs_to :product
11
- # end
88
+ # @return [Hash]
12
89
  #
13
- # @param [Symbol] model_name
14
- # @param [#to_hash] options options for setting up the relationship
15
- # @option options [String] :class_name Override the default class name
16
- # @option options [String] :readonly (false) Whether to serialize
17
- # this attribute
90
+ # @api private
91
+ def collection_proxies
92
+ @collection_proxies ||= {}
93
+ end
94
+
95
+ # Setup a child collection proxy on first instantation
18
96
  #
19
- # @return [undefined]
97
+ # @return [Hash]
20
98
  #
21
- # @api public
22
- def belongs_to(model_name, options={})
23
- class_name = options[:class_name] || model_name.to_s.classify
24
- foreign_key = model_name.to_s.foreign_key.to_sym
99
+ # @api private
100
+ def build_collection_proxy(target, association_name:, class_name:, embedded:)
101
+ CollectionProxy.new({
102
+ parent: self,
103
+ target: target,
104
+ embedded: embedded,
105
+ class_name: class_name,
106
+ association_name: association_name
107
+ })
108
+ end
109
+ end
25
110
 
26
- define_method model_name do
27
- if (id = attributes[foreign_key])
28
- @client.adapter_for(class_name).find(id)
29
- end
30
- end
31
- attribute foreign_key, Integer, readonly: options[:readonly]
111
+ # Provides a convenient wrapper for a collection of child records.
112
+ # Exposes both an Enumerable interface as well as the ability
113
+ # to create new child records
114
+ class CollectionProxy
115
+ include Enumerable
116
+ delegate :each, :empty?, to: :@target
117
+
118
+ attr_reader :association_name, :parent
119
+
120
+ # Setup the child collection proxy
121
+ #
122
+ # @return [Hash]
123
+ #
124
+ # @api private
125
+ def initialize(parent:, association_name:, class_name:, target:, embedded:)
126
+ @parent = parent
127
+ @target = target
128
+ @embedded = embedded
129
+ @class_name = class_name
130
+ @association_name = association_name
32
131
  end
33
132
 
34
- # Set up a has_many relationship between two classes based on a
35
- # JSON key of {class_name}_ids.
133
+ # Build a new child object inside the collection
36
134
  #
37
135
  # @example
38
- # class Gecko::Record::Product
39
- # has_many :variants
40
- # end
136
+ # item = order.order_line_items.build(variant_id: 1234, quantiy: 12.5, price: 13.45)
137
+ # order.order_line_items.include?(item) #=> true
41
138
  #
42
- # @param [Symbol] model_name
43
- # @param [#to_hash] options options for setting up the relationship
44
- # @option options [String] :class_name Override the default class name
45
- # @option options [String] :readonly (true) Whether to serialize this
46
- # attribute
139
+ # @param [#to_hash] attributes for the child record
47
140
  #
48
- # @return [undefined]
141
+ # @return [Gecko::Record::Base]
49
142
  #
50
143
  # @api public
51
- def has_many(association_name, options={})
52
- model_name = association_name.to_s.singularize
53
- class_name = options[:class_name] || model_name.classify
54
- foreign_key = model_name.foreign_key.pluralize.to_sym
55
- readonly = options.key?(:readonly) ? options[:readonly] : true
56
-
57
- define_method association_name do
58
- ids = self.attributes[foreign_key]
59
- if ids.any?
60
- @client.adapter_for(class_name).find_many(ids)
61
- else
62
- []
63
- end
144
+ def build(attributes)
145
+ if @parent.persisted?
146
+ parent_foreign_key = @parent.class.demodulized_name.foreign_key.to_sym
147
+ attributes[parent_foreign_key] = @parent.id
64
148
  end
65
- attribute foreign_key, Array[Integer], readonly: readonly
149
+
150
+ record = client.adapter_for(@class_name).build(attributes)
151
+ @target << record
152
+ record
153
+ end
154
+
155
+ # Should this collection of records be serialized inside it's parent object
156
+ #
157
+ # @return [Boolean]
158
+ #
159
+ # @api private
160
+ def embed_records?
161
+ !!@embedded
162
+ end
163
+
164
+ private
165
+
166
+ # Access the Gecko Client object
167
+ #
168
+ # @return [Gecko::Client]
169
+ #
170
+ # @api private
171
+ def client
172
+ @parent.instance_variable_get(:@client)
66
173
  end
67
174
  end
68
175
  end
@@ -30,6 +30,11 @@ module Gecko
30
30
  next unless writeable?(attribute)
31
31
  serialize_attribute(attribute_hash, attribute)
32
32
  end
33
+
34
+ embedded_collections_for_serialization.each do |collection|
35
+ serialize_new_records(attribute_hash, collection)
36
+ end
37
+
33
38
  attribute_hash
34
39
  end
35
40
 
@@ -96,6 +101,33 @@ module Gecko
96
101
  def root
97
102
  self.class.demodulized_name.underscore.to_sym
98
103
  end
104
+
105
+ private
106
+
107
+ # Returns embedded collections
108
+ #
109
+ # @return [Array<Gecko::Helpers::CollectionProxy>]
110
+ #
111
+ # @api private
112
+ def embedded_collections_for_serialization
113
+ collection_proxies.values.select(&:embed_records?)
114
+ end
115
+
116
+ # Serialize newly built embedded records into the payload
117
+ #
118
+ # @return [undefined]
119
+ #
120
+ # @api private
121
+ def serialize_new_records(serialized, collection_proxy)
122
+ new_records = collection_proxy.reject(&:persisted?)
123
+ return unless new_records.any?
124
+
125
+ parent_key = collection_proxy.parent.class.demodulized_name.foreign_key.to_sym
126
+
127
+ serialized[collection_proxy.association_name] = new_records.map do |record|
128
+ record.serializable_hash.except(parent_key)
129
+ end
130
+ end
99
131
  end
100
132
  end
101
133
  end
@@ -7,7 +7,7 @@ module Gecko
7
7
  module Record
8
8
  class Base
9
9
  include Virtus.model
10
- extend Gecko::Helpers::AssociationHelper
10
+ include Gecko::Helpers::AssociationHelper
11
11
  include Gecko::Helpers::InspectionHelper
12
12
  include Gecko::Helpers::SerializationHelper
13
13
  include Gecko::Helpers::ValidationHelper
@@ -78,7 +78,7 @@ module Gecko
78
78
  def find_many(ids)
79
79
  existing, required = ids.partition { |id| has_record_for_id?(id) }
80
80
  if required.any?
81
- where(ids: required) + existing.map { |id| record_for_id(id) }
81
+ where(ids: ids) + existing.map { |id| record_for_id(id) }
82
82
  else
83
83
  existing.map { |id| record_for_id(id) }
84
84
  end
@@ -9,7 +9,7 @@ module Gecko
9
9
  belongs_to :billing_address, class_name: 'Address'
10
10
  belongs_to :stock_location, class_name: 'Location'
11
11
 
12
- has_many :fulfillment_line_items
12
+ has_many :fulfillment_line_items, embedded: true
13
13
 
14
14
  attribute :status, String
15
15
  attribute :exchange_rate, String
@@ -8,7 +8,7 @@ module Gecko
8
8
  belongs_to :billing_address
9
9
  belongs_to :payment_term
10
10
 
11
- has_many :invoice_line_items
11
+ has_many :invoice_line_items, embedded: true
12
12
 
13
13
  attribute :invoice_number, String
14
14
  attribute :invoiced_at, Date
@@ -5,7 +5,7 @@ module Gecko
5
5
  class Order < Base
6
6
  has_many :fulfillments
7
7
  has_many :invoices
8
- has_many :order_line_items
8
+ has_many :order_line_items, embedded: true
9
9
 
10
10
  belongs_to :company
11
11
  belongs_to :contact
@@ -24,9 +24,6 @@ module Gecko
24
24
  attribute :position, Integer
25
25
 
26
26
  attribute :image_url, String, readonly: true
27
-
28
- # DEPRECATED
29
- attribute :tax_rate, BigDecimal
30
27
  end
31
28
 
32
29
  class OrderLineItemAdapter < BaseAdapter
@@ -1,3 +1,3 @@
1
1
  module Gecko
2
- VERSION = '0.2.6'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -33,7 +33,7 @@ class Gecko::Helpers::AssociationHelperTest < Minitest::Test
33
33
  def test_has_many_without_ids
34
34
  record = @klass.new(@client, {order_ids: []})
35
35
  @client.Order.expects(:find_many).never
36
- assert_equal([], record.orders)
36
+ assert_empty(record.orders)
37
37
  end
38
38
 
39
39
  def test_belongs_to
@@ -53,4 +53,27 @@ class Gecko::Helpers::AssociationHelperTest < Minitest::Test
53
53
  @client.Order.expects(:find).with(56)
54
54
  record.small_order
55
55
  end
56
+
57
+ def test_building_a_new_embedded_item
58
+ record = @client.Order.build({})
59
+ embedded = record.order_line_items.build(quantity: 1, variant_id: 1)
60
+ assert_instance_of(Gecko::Record::OrderLineItem, embedded)
61
+ assert_nil(embedded.order_id)
62
+ assert_instance_of(Gecko::Record::OrderLineItem, embedded)
63
+ assert(!embedded.persisted?)
64
+ assert_includes(record.order_line_items, embedded)
65
+ skip("This hasn't been implemented for fresh records yet")
66
+ assert_equal(record, embedded.order)
67
+ end
68
+
69
+ def test_building_a_new_embedded_item_on_existing_record
70
+ record = @client.Order.instantiate_and_register_record(id: 123)
71
+ embedded = record.order_line_items.build(quantity: 1, variant_id: 1)
72
+ assert_instance_of(Gecko::Record::OrderLineItem, embedded)
73
+ assert_equal(123, embedded.order_id)
74
+ assert_instance_of(Gecko::Record::OrderLineItem, embedded)
75
+ assert(!embedded.persisted?)
76
+ assert_includes(record.order_line_items, embedded)
77
+ assert_equal(record, embedded.order)
78
+ end
56
79
  end
@@ -80,6 +80,22 @@ class Gecko::Helpers::SerializationHelperTest < Minitest::Test
80
80
  assert_equal(:order_line_item, record.root)
81
81
  end
82
82
 
83
+ def test_serializing_new_embedded_items
84
+ record = Gecko::Record::Order.new(@client, {})
85
+ record.order_line_items.build(quantity: 1, variant_id: 1)
86
+ serialized = record.serializable_hash
87
+ assert(1, serialized[:order_line_items].length)
88
+ assert_equal(1, serialized[:order_line_items][0][:variant_id])
89
+ assert_equal('1.0', serialized[:order_line_items][0][:quantity])
90
+ assert(!serialized[:order_line_items][0].key?(:order_id))
91
+ end
92
+
93
+ def test_doesnt_add_embedded_keys_unless_required
94
+ record = Gecko::Record::Order.new(@client, {})
95
+ serialized = record.serializable_hash
96
+ assert(!serialized.key?(:order_line_items))
97
+ end
98
+
83
99
  private
84
100
 
85
101
  def serialized_record
@@ -8,7 +8,7 @@ module SharedSideloadedDataParsingExamples
8
8
  child_adapter = @client.adapter_for(child.singularize.classify)
9
9
 
10
10
  identity_map = child_adapter.instance_variable_get(:@identity_map)
11
- child_collection = collection.flat_map { |record| record.send(child) }
11
+ child_collection = collection.flat_map { |record| record.send(child).to_a }
12
12
 
13
13
  assert_equal child_collection, identity_map.values
14
14
  end
@@ -1,7 +1,7 @@
1
1
  require 'gecko'
2
2
  require 'minitest/autorun'
3
3
  require 'minitest/pride'
4
- require 'mocha/mini_test'
4
+ require 'mocha/minitest'
5
5
  require 'vcr'
6
6
  require 'webmock/minitest'
7
7
  require 'timecop'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gecko-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bradley Priest
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-19 00:00:00.000000000 Z
11
+ date: 2018-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -154,16 +154,16 @@ dependencies:
154
154
  name: oauth2
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ">="
157
+ - - ">"
158
158
  - !ruby/object:Gem::Version
159
- version: '0'
159
+ version: 1.1.0
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - ">="
164
+ - - ">"
165
165
  - !ruby/object:Gem::Version
166
- version: '0'
166
+ version: 1.1.0
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: virtus
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -356,7 +356,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
356
356
  - !ruby/object:Gem::Version
357
357
  version: '0'
358
358
  requirements: []
359
- rubygems_version: 3.0.3
359
+ rubyforge_project:
360
+ rubygems_version: 2.7.6
360
361
  signing_key:
361
362
  specification_version: 4
362
363
  summary: A Ruby interface to the TradeGecko API.