gecko-ruby 0.2.6 → 0.5.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
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.