primalize-jsonapi 0.1.4 → 0.1.5

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: 3350f0fd1aad3c862179c3a156a3d664bcf178d2e03205a67c77c735f9537fd5
4
- data.tar.gz: 61448a12418885035336205324c3755a9556d25d60a7f9cfc332b02ab9fcaab2
3
+ metadata.gz: 3392a354c12975c1f43bdc043afcbae8a7596289f4705c07ce12f39c287cf8cd
4
+ data.tar.gz: '097d8258d2137658be6f994732b35e0cd57848481a369bf1bb5bee31ac2ee084'
5
5
  SHA512:
6
- metadata.gz: 1066244c0722528c54ac831365f11f9711a8ad9e45102d11e237c0530848b8fb2fddffc1a5da592bf8a86080ebc4829215c3aec71a93c7d798c0172f0aab836e
7
- data.tar.gz: 4f9821abd4eb1c960136298faf5a33e88a892a6e54a9b6edfd41e07b827a1ca8413d66736a343b4ae4d9909d7064e35b736afafc3f1bdef6789a2e7707f2b62b
6
+ metadata.gz: 0ad30361cccc42f2210e46e28aaec79b9a0624c23625b17aee02d5726b3842a2dec16e994df89cd5eb72fca29d0089d2230ce705a822d80f64c413af5d64cfec
7
+ data.tar.gz: 50c36d15c05656c64c3cc4f9c3163432c7c7479fb93b2581ced4529c1abe1865d1cf619cf4982f236e8315930c7420d8336dc930b2fb0de0ce47735fed4b382b
@@ -1,9 +1,34 @@
1
1
  require 'primalize/jsonapi/version'
2
2
  require 'primalize/single'
3
- require 'primalize/many'
4
3
 
5
4
  module Primalize
6
5
  module JSONAPI
6
+ @model_type_cache = {}
7
+ @serializer_map = {}
8
+
9
+ def self.serialize include: [], **models
10
+ if models.one?
11
+ type = models.each_key.first
12
+ cache = Cache.new
13
+ Array(models[type])
14
+ .map { |model| self[type].new(model, include: include, cache: cache).call }
15
+ .reduce({ data: [] }) { |result, hash|
16
+ result.merge!(hash) do |key, left, right|
17
+ case key
18
+ when :data
19
+ left + right
20
+ when :included
21
+ (left + right).tap(&:uniq!)
22
+ else
23
+ left.merge!(right)
24
+ end
25
+ end
26
+ }
27
+ else
28
+ raise ArgumentError, "cannot supply more than one resource type"
29
+ end
30
+ end
31
+
7
32
  class Relationships
8
33
  def initialize
9
34
  @rels = []
@@ -34,9 +59,9 @@ module Primalize
34
59
 
35
60
  class HasMany
36
61
  attr_reader :attr
37
- def initialize attr, &block
62
+ def initialize attr, type: attr, &block
38
63
  @attr = attr
39
- @block = block
64
+ @block = block || proc { JSONAPI.fetch(type) }
40
65
  end
41
66
 
42
67
  def call(model, cache:)
@@ -54,7 +79,7 @@ module Primalize
54
79
  def metadata(model, cache:)
55
80
  result = model.send(@attr).map do |obj|
56
81
  cache.fetch(:metadata, obj) do
57
- MetadataPrimalizer.new(obj).call
82
+ MetadataPrimalizer.new(obj, primalizer.type).call
58
83
  end
59
84
  end
60
85
 
@@ -64,9 +89,9 @@ module Primalize
64
89
 
65
90
  class HasOne
66
91
  attr_reader :attr
67
- def initialize attr, &block
92
+ def initialize attr, type: attr, &block
68
93
  @attr = attr
69
- @block = block
94
+ @block = block || proc { JSONAPI.fetch(type) }
70
95
  end
71
96
 
72
97
  def call(model, cache:)
@@ -82,17 +107,22 @@ module Primalize
82
107
 
83
108
  def metadata(model, cache:)
84
109
  model = model.send(@attr)
85
- cache.fetch(:metadata, model) do
86
- { data: MetadataPrimalizer.new(model).call }
110
+ data = cache.fetch(:metadata, model) do
111
+ MetadataPrimalizer.new(model, primalizer.type).call
87
112
  end
113
+
114
+ { data: data }
88
115
  end
89
116
  end
90
117
 
91
118
  class MetadataPrimalizer < Single
92
119
  attributes(id: string(&:to_s), type: string)
93
120
 
94
- def type
95
- object.class.name.gsub(/(.)([A-Z])/, '\1_\2').downcase
121
+ attr_reader :type
122
+
123
+ def initialize model, type
124
+ super model
125
+ @type = type.to_s
96
126
  end
97
127
  end
98
128
 
@@ -107,40 +137,51 @@ module Primalize
107
137
  end
108
138
 
109
139
  def [] type, model
140
+ return if model.nil?
141
+
110
142
  @cache[type][model.class][model.id]
111
143
  end
112
144
 
113
145
  def []= type, model, value
146
+ return if model.nil?
147
+
114
148
  @cache[type][model.class][model.id] = value
115
149
  end
116
150
 
117
151
  def fetch type, model
152
+ return if model.nil?
153
+
118
154
  @cache[type][model.class][model.id] ||= yield
119
155
  end
120
156
  end
121
157
 
122
- @serializer_map = {}
158
+ def self.[]= type, serializer
159
+ @serializer_map[type] = serializer
160
+ end
123
161
 
124
- def self.[]= model_class, serializer
125
- @serializer_map[model_class] = serializer
162
+ def self.fetch type
163
+ @serializer_map.fetch type do
164
+ raise ArgumentError,
165
+ "No Primalize::JSONAPI primalizer defined for #{type.inspect}"
166
+ end
126
167
  end
127
168
 
128
- def self.[] model_class=nil, **options
129
- @serializer_map[model_class] ||= Class.new(Single) do
130
- @model_class = model_class
169
+ def self.[] type=nil, **options
170
+ @serializer_map[type] ||= Class.new(Single) do
171
+ @_type = type
131
172
 
132
173
  # This is useful for situations like this:
133
- # class MySerializer < Primalize::JSONAPI[MyModel]
174
+ # class MySerializer < Primalize::JSONAPI[:movies]
134
175
  # end
135
176
  define_singleton_method :inherited do |inheriting_class|
136
- JSONAPI[model_class] = inheriting_class
177
+ JSONAPI[type] = inheriting_class
137
178
  end
138
179
 
139
- def self.model_class
140
- if @model_class
141
- @model_class
180
+ def self.type
181
+ if @_type
182
+ @_type
142
183
  else
143
- superclass.model_class
184
+ superclass.type
144
185
  end
145
186
  end
146
187
 
@@ -159,6 +200,25 @@ module Primalize
159
200
 
160
201
  define_singleton_method :attribute_primalizer do
161
202
  @attribute_primalizer ||= Class.new(Single) do
203
+ def initialize model, original:
204
+ super model
205
+ @original = original
206
+ end
207
+
208
+ def self.attributes(**attrs)
209
+ super
210
+
211
+ attrs.each do |attr, type|
212
+ define_method attr do
213
+ if @original.respond_to? attr
214
+ @original.class.new(object).public_send attr
215
+ else
216
+ object.public_send attr
217
+ end
218
+ end
219
+ end
220
+ end
221
+
162
222
  define_singleton_method :to_s do
163
223
  "#{original_primalizer}.model_primalizer.attribute_primalizer"
164
224
  end
@@ -183,26 +243,28 @@ module Primalize
183
243
  id: string(&:to_s),
184
244
  type: string,
185
245
  attributes: object,
186
- relationships: object,
246
+ relationships: optional(object),
187
247
  )
188
248
 
189
249
  attr_reader :cache
190
250
 
191
- def initialize model, cache: Cache.new
192
- super(model)
251
+ def initialize model, original:, include: [], cache: Cache.new
252
+ super model
253
+ @original = original
254
+ @include = include
193
255
  @cache = cache
194
256
  end
195
257
 
196
- def self.name
197
- 'ModelPrimalizer'
258
+ define_method :type do
259
+ original_primalizer.type.to_s
198
260
  end
199
261
 
200
- def type
201
- object.class.name.gsub(/(.)([A-Z])/, '\1_\2').downcase
262
+ def attributes
263
+ self.class.attribute_primalizer.new(object, original: @original).call
202
264
  end
203
265
 
204
- def attributes
205
- self.class.attribute_primalizer.new(object).call
266
+ def call
267
+ super.tap(&:compact!)
206
268
  end
207
269
 
208
270
  def relationships
@@ -228,7 +290,7 @@ module Primalize
228
290
  attr_reader :cache
229
291
 
230
292
  def initialize models, include: [], meta: nil, cache: Cache.new
231
- super Array(models)
293
+ super models
232
294
 
233
295
  @include = include
234
296
  @meta = meta
@@ -245,7 +307,7 @@ module Primalize
245
307
  included = Set.new
246
308
 
247
309
  @include.each do |rel|
248
- object.each do |model|
310
+ Array(object).each do |model|
249
311
  primalizer = self.class.model_primalizer.relationships[rel]
250
312
  relationship = primalizer.call(model, cache: cache)
251
313
 
@@ -271,8 +333,8 @@ module Primalize
271
333
  end
272
334
 
273
335
  def data
274
- object.map do |model|
275
- self.class.model_primalizer.new(model, cache: cache).call
336
+ Array(object).map do |model|
337
+ self.class.model_primalizer.new(model, original: self, include: @include, cache: cache).call
276
338
  end
277
339
  end
278
340
  end
@@ -1,5 +1,5 @@
1
1
  module Primalize
2
2
  module JSONAPI
3
- VERSION = "0.1.4"
3
+ VERSION = "0.1.5"
4
4
  end
5
5
  end
@@ -0,0 +1,428 @@
1
+ require 'benchmark/ips'
2
+ $:.unshift 'lib'
3
+ $:.unshift '../active_model_serializers/lib'
4
+ require 'active_model_serializers'
5
+ require 'primalize/jsonapi'
6
+ require 'grand_central/model'
7
+ require 'ffaker'
8
+ require 'securerandom'
9
+
10
+ class Model < GrandCentral::Model
11
+ def read_attribute_for_serialization attr
12
+ public_send attr
13
+ end
14
+ end
15
+
16
+ class Article < Model
17
+ attributes :id, :title, :body, :view_count, :author, :comments
18
+
19
+ def author_id(*args)
20
+ author&.id
21
+ end
22
+
23
+ def comment_ids
24
+ comments.map(&:id)
25
+ end
26
+ end
27
+
28
+ class Person < Model
29
+ attributes :id, :name, :email
30
+ end
31
+
32
+ class Comment < Model
33
+ attributes :id, :body, :author
34
+ end
35
+
36
+ class ArticlePrimalizer < Primalize::JSONAPI[:articles]
37
+ attributes(
38
+ title: string,
39
+ body: string,
40
+ view_count: integer,
41
+ )
42
+
43
+ has_one :author, type: :people
44
+ has_many :comments
45
+ end
46
+
47
+ class PersonPrimalizer < Primalize::JSONAPI[:people]
48
+ attributes(
49
+ name: string,
50
+ email: string,
51
+ )
52
+ end
53
+
54
+ class CommentPrimalizer < Primalize::JSONAPI[:comments]
55
+ attributes(
56
+ body: string,
57
+ author_name: string,
58
+ )
59
+ alias comment object
60
+
61
+ def author_name
62
+ comment.author.name
63
+ end
64
+ end
65
+
66
+ ActiveModel::Serializer.config.adapter = :json_api
67
+ ActiveModel::Serializer.config.key_transform = :underscore
68
+ ActiveModelSerializers.logger = ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new('/dev/null'))
69
+
70
+ class ArticleSerializer < ActiveModel::Serializer
71
+ attributes :title, :body, :view_count
72
+
73
+ belongs_to :author
74
+ has_many :comments
75
+ end
76
+
77
+ class PersonSerializer < ActiveModel::Serializer
78
+ attributes :name, :email
79
+ end
80
+
81
+ class CommentSerializer < ActiveModel::Serializer
82
+ attributes :body, :author_name
83
+
84
+ def author_name
85
+ object.author.name
86
+ end
87
+ end
88
+
89
+ require 'fast_jsonapi'
90
+ module Netflix
91
+ class ArticleSerializer
92
+ include FastJsonapi::ObjectSerializer
93
+
94
+ set_type :articles
95
+
96
+ attributes :title, :body, :view_count
97
+
98
+ belongs_to :author
99
+ has_many :comments
100
+ end
101
+
102
+ class PersonSerializer
103
+ include FastJsonapi::ObjectSerializer
104
+
105
+ set_type :people
106
+
107
+ attributes :name, :email
108
+ end
109
+ AuthorSerializer = PersonSerializer
110
+
111
+ class CommentSerializer
112
+ include FastJsonapi::ObjectSerializer
113
+
114
+ set_type :comments
115
+
116
+ attributes :body
117
+ attribute :author_name do |comment|
118
+ comment.author.name
119
+ end
120
+ end
121
+ end
122
+
123
+ require 'primalize'
124
+ # require 'oj'
125
+ module Response
126
+ class ArticlePrimalizer < Primalize::Single
127
+ attributes(
128
+ id: integer,
129
+ title: string,
130
+ body: string,
131
+ view_count: integer,
132
+ author_id: integer,
133
+ comment_ids: array(integer),
134
+ )
135
+ alias article object
136
+
137
+ def author_id
138
+ article.author.id
139
+ end
140
+
141
+ def comment_ids
142
+ article.comments.map(&:id)
143
+ end
144
+ end
145
+
146
+ class PersonPrimalizer < Primalize::Single
147
+ attributes(
148
+ id: integer,
149
+ name: string,
150
+ email: string,
151
+ )
152
+ end
153
+
154
+ class CommentPrimalizer < Primalize::Single
155
+ attributes(
156
+ id: integer,
157
+ body: string,
158
+ author_name: string,
159
+ )
160
+ alias comment object
161
+
162
+ def author_name
163
+ comment.author.name
164
+ end
165
+ end
166
+
167
+ class Response < Primalize::Many
168
+ # def to_json
169
+ # Oj.dump call, mode: :json
170
+ # end
171
+ end
172
+
173
+ class ArticlesResponse < Response
174
+ attributes(
175
+ articles: enumerable(ArticlePrimalizer),
176
+ )
177
+ end
178
+
179
+ class ArticlesResponseWithAssociations < ArticlesResponse
180
+ attributes(
181
+ authors: enumerable(PersonPrimalizer),
182
+ comments: enumerable(CommentPrimalizer),
183
+ )
184
+
185
+ def initialize articles:, authors: articles.flat_map(&:author).uniq, comments: articles.flat_map(&:comments)
186
+ super(
187
+ articles: articles,
188
+ authors: authors,
189
+ comments: comments,
190
+ )
191
+ end
192
+ end
193
+
194
+ class ArticleResponse < Primalize::Many
195
+ attributes(
196
+ article: ArticlePrimalizer,
197
+ )
198
+ end
199
+
200
+ class ArticleResponseWithAssociations < ArticleResponse
201
+ attributes(
202
+ author: PersonPrimalizer,
203
+ comments: enumerable(CommentPrimalizer),
204
+ )
205
+
206
+ def initialize article:, author: article.author, comments: article.comments
207
+ super(
208
+ article: article,
209
+ author: author,
210
+ comments: comments,
211
+ )
212
+ end
213
+ end
214
+ end
215
+
216
+ people = Array.new(10) do |i|
217
+ Person.new(
218
+ id: i,
219
+ name: FFaker::Name.name,
220
+ email: FFaker::Internet.email,
221
+ )
222
+ end
223
+ comment_id = 0
224
+ articles = Array.new(25) do |i|
225
+ Article.new(
226
+ id: i,
227
+ title: 'Foo',
228
+ body: 'Lorem ipsum dolor sit amet omg lol wtf bbq lmao rofl',
229
+ view_count: 12,
230
+ author: people.sample,
231
+ comments: Array.new(SecureRandom.random_number(0..10)) do
232
+ Comment.new(
233
+ id: comment_id += 1,
234
+ body: 'lol this is a comment and i am writing it',
235
+ author: people.sample,
236
+ )
237
+ end,
238
+ )
239
+ end
240
+ article = articles.first
241
+
242
+ primalized = ArticlePrimalizer.new(articles, include: %i(author comments)).call.tap { |hash| hash[:included].sort_by! { |id:, type:, **| [type, id] } }
243
+ ams = ActiveModelSerializers::SerializableResource.new(articles, include: %i(author comments).join(',')).as_json.tap { |hash| hash[:included].sort_by! { |id:, type:, **| [type, id] } }
244
+
245
+ pp(
246
+ single_no_associations: pp(Primalize::JSONAPI.serialize(articles: article)) == pp(ActiveModelSerializers::SerializableResource.new([article]).as_json),
247
+ multi_no_associations: Primalize::JSONAPI.serialize(articles: articles) == ActiveModelSerializers::SerializableResource.new(articles).as_json,
248
+ single_with_associations: Primalize::JSONAPI.serialize(
249
+ articles: article,
250
+ include: %i(author comments),
251
+ ) == ActiveModelSerializers::SerializableResource.new(
252
+ [article],
253
+ include: %i(author comments),
254
+ ).as_json,
255
+ multi_with_associations: primalized == ams,
256
+ )
257
+
258
+ pp Response::ArticlesResponse.new(articles: articles).call
259
+ require 'pry'
260
+ binding.pry
261
+
262
+ puts 'SINGLE OBJECT, NO ASSOCIATIONS, TO HASH'
263
+ Benchmark.ips do |x|
264
+ x.report 'Primalize::JSONAPI' do
265
+ ArticlePrimalizer.new(article).call
266
+ end
267
+
268
+ x.report 'AMS' do
269
+ ActiveModelSerializers::SerializableResource.new(article).as_json
270
+ end
271
+
272
+ x.report 'FastJsonapi' do
273
+ Netflix::ArticleSerializer.new(article).as_json
274
+ end
275
+
276
+ x.report 'Primalize::Many' do
277
+ Response::ArticleResponse.new(article: article).call
278
+ end
279
+
280
+ x.compare!
281
+ end
282
+
283
+ puts 'SINGLE OBJECT, W/ ASSOCIATIONS, TO HASH'
284
+ Benchmark.ips do |x|
285
+ x.report 'Primalize::JSONAPI' do
286
+ ArticlePrimalizer.new(article, include: %i(author comments)).call
287
+ end
288
+
289
+ x.report 'AMS' do
290
+ ActiveModelSerializers::SerializableResource.new(article, include: %i(author comments)).as_json
291
+ end
292
+
293
+ x.report 'FastJsonapi' do
294
+ Netflix::ArticleSerializer.new(article, include: %w(author comments)).as_json
295
+ end
296
+
297
+ x.report 'Primalize::Many' do
298
+ Response::ArticleResponseWithAssociations.new(article: article).call
299
+ end
300
+
301
+ x.compare!
302
+ end
303
+
304
+ puts 'MULTIPLE OBJECTS, NO ASSOCIATIONS, TO HASH'
305
+ Benchmark.ips do |x|
306
+ x.report 'Primalize::JSONAPI' do
307
+ ArticlePrimalizer.new(articles).call
308
+ end
309
+
310
+ x.report 'AMS' do
311
+ ActiveModelSerializers::SerializableResource.new(articles).as_json
312
+ end
313
+
314
+ x.report 'FastJsonapi' do
315
+ Netflix::ArticleSerializer.new(articles).as_json
316
+ end
317
+
318
+ x.report 'Primalize::Many' do
319
+ Response::ArticlesResponse.new(articles: articles).call
320
+ end
321
+
322
+ x.compare!
323
+ end
324
+
325
+ puts 'MULTIPLE OBJECTS, W/ ASSOCIATIONS, TO HASH'
326
+ Benchmark.ips do |x|
327
+ x.report 'Primalize::JSONAPI' do
328
+ Primalize::JSONAPI.serialize(articles: articles, include: %i(author comments))
329
+ end
330
+
331
+ x.report 'AMS' do
332
+ ActiveModelSerializers::SerializableResource.new(articles, include: %i(author comments)).as_json
333
+ end
334
+
335
+ x.report 'FastJsonapi' do
336
+ Netflix::ArticleSerializer.new(articles, include: %i(author comments)).as_json
337
+ end
338
+
339
+ x.report 'Primalize::Many' do
340
+ Response::ArticlesResponseWithAssociations.new(articles: articles).call
341
+ end
342
+
343
+ x.compare!
344
+ end
345
+
346
+ puts 'SINGLE OBJECT, NO ASSOCIATIONS, TO STRING'
347
+ Benchmark.ips do |x|
348
+ x.report 'Primalize::JSONAPI' do
349
+ ArticlePrimalizer.new(article).to_json
350
+ end
351
+
352
+ x.report 'AMS' do
353
+ ActiveModelSerializers::SerializableResource.new(article).to_json
354
+ end
355
+
356
+ x.report 'FastJsonapi' do
357
+ Netflix::ArticleSerializer.new(article).to_json
358
+ end
359
+
360
+ x.report 'Primalize::Many' do
361
+ Response::ArticleResponse.new(article: article).to_json
362
+ end
363
+
364
+ x.compare!
365
+ end
366
+
367
+ puts 'SINGLE OBJECT, W/ ASSOCIATIONS, TO STRING'
368
+ Benchmark.ips do |x|
369
+ x.report 'Primalize::JSONAPI' do
370
+ ArticlePrimalizer.new(article, include: %i(author comments)).to_json
371
+ end
372
+
373
+ x.report 'AMS' do
374
+ ActiveModelSerializers::SerializableResource.new(article, include: %i(author comments)).to_json
375
+ end
376
+
377
+ x.report 'FastJsonapi' do
378
+ Netflix::ArticleSerializer.new(article, include: %i(author comments)).to_json
379
+ end
380
+
381
+ x.report 'Primalize::Many' do
382
+ Response::ArticleResponseWithAssociations.new(article: article).to_json
383
+ end
384
+
385
+ x.compare!
386
+ end
387
+
388
+ puts 'MULTIPLE OBJECTS, NO ASSOCIATIONS, TO STRING'
389
+ Benchmark.ips do |x|
390
+ x.report 'Primalize::JSONAPI' do
391
+ ArticlePrimalizer.new(articles).to_json
392
+ end
393
+
394
+ x.report 'AMS' do
395
+ ActiveModelSerializers::SerializableResource.new(articles).to_json
396
+ end
397
+
398
+ x.report 'FastJsonapi' do
399
+ Netflix::ArticleSerializer.new(articles).to_json
400
+ end
401
+
402
+ x.report 'Primalize::Many' do
403
+ Response::ArticlesResponse.new(articles: articles).to_json
404
+ end
405
+
406
+ x.compare!
407
+ end
408
+
409
+ puts 'MULTIPLE OBJECTS, W/ ASSOCIATIONS, TO STRING'
410
+ Benchmark.ips do |x|
411
+ x.report 'Primalize::JSONAPI' do
412
+ Primalize::JSONAPI.serialize(articles: articles, include: %i(author comments)).to_json
413
+ end
414
+
415
+ x.report 'AMS' do
416
+ ActiveModelSerializers::SerializableResource.new(articles, include: %i(author comments)).to_json
417
+ end
418
+
419
+ x.report 'FastJsonapi' do
420
+ Netflix::ArticleSerializer.new(articles, include: %w(author comments)).to_json
421
+ end
422
+
423
+ x.report 'Primalize::Many' do
424
+ Response::ArticlesResponseWithAssociations.new(articles: articles).to_json
425
+ end
426
+
427
+ x.compare!
428
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primalize-jsonapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Gaskins
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-11 00:00:00.000000000 Z
11
+ date: 2018-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: primalize
@@ -113,6 +113,7 @@ files:
113
113
  - bin/setup
114
114
  - lib/primalize/jsonapi.rb
115
115
  - lib/primalize/jsonapi/version.rb
116
+ - performance/benchmark.rb
116
117
  - primalize-jsonapi.gemspec
117
118
  homepage: https://github.com/jgaskins/primalize-jsonapi
118
119
  licenses:
@@ -134,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
135
  version: '0'
135
136
  requirements: []
136
137
  rubyforge_project:
137
- rubygems_version: 2.7.3
138
+ rubygems_version: 2.7.6
138
139
  signing_key:
139
140
  specification_version: 4
140
141
  summary: JSON API support for the Primalize gem