ar_serializer 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e9144cab6ef520e2c0734bbe98a13a046f3b7b8411310ccc522dc999bae5365
4
- data.tar.gz: d938b8684bbb22937c97c2572994b6bd11b38c72011f1b19975d96c7633656c7
3
+ metadata.gz: f5dcdb4d958a8a3c5f45333e6d046d8070b817e9ace01ff9c5129421117a4d96
4
+ data.tar.gz: 3e37de9cd29f69b6a9fc98a297fc40eb700127403e01604cc779f0225ecd2196
5
5
  SHA512:
6
- metadata.gz: a7ff7ed23abaabef6893c31dc259ce18eeb3111df652c4e4a2d717523853e4a4f27119ddb0d027583ae788b218fdea73abebfc5de99480447e51bbabe04929f9
7
- data.tar.gz: 8bceb19d2f319772e575c440870d074431f21efeab16375dced2e87637791e3d94927f0024c01bfd9669f0e0fb9743539f17ac47b12233a056db64e12b952264
6
+ metadata.gz: e6f6050647dfe4baf84dd2801c3158447c91653dd70894a92a9eedd8c1a3b84e6da8182854ccf380f0c66ed4927774d83ed5dfc8c327d1d9ab9189c71d10d0bc
7
+ data.tar.gz: ac83b599db7be347c547b7bd1a6a3a2b0d28825220df5d862899151fe26d1aa4843a34851e3af683d7ff2245b4d904cfbf191a1a5e837dd7758b57cb7023fb83
data/Gemfile.lock CHANGED
@@ -1,33 +1,32 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ar_serializer (1.0.0)
4
+ ar_serializer (1.1.0)
5
5
  activerecord
6
6
  top_n_loader
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (5.2.3)
12
- activesupport (= 5.2.3)
13
- activerecord (5.2.3)
14
- activemodel (= 5.2.3)
15
- activesupport (= 5.2.3)
16
- arel (>= 9.0)
17
- activesupport (5.2.3)
11
+ activemodel (6.0.2.1)
12
+ activesupport (= 6.0.2.1)
13
+ activerecord (6.0.2.1)
14
+ activemodel (= 6.0.2.1)
15
+ activesupport (= 6.0.2.1)
16
+ activesupport (6.0.2.1)
18
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
19
18
  i18n (>= 0.7, < 2)
20
19
  minitest (~> 5.1)
21
20
  tzinfo (~> 1.1)
22
- arel (9.0.0)
21
+ zeitwerk (~> 2.2)
23
22
  coderay (1.1.2)
24
23
  concurrent-ruby (1.1.5)
25
24
  docile (1.3.1)
26
- i18n (1.6.0)
25
+ i18n (1.7.0)
27
26
  concurrent-ruby (~> 1.0)
28
27
  json (2.1.0)
29
28
  method_source (0.9.2)
30
- minitest (5.11.3)
29
+ minitest (5.13.0)
31
30
  pry (0.12.2)
32
31
  coderay (~> 1.1.0)
33
32
  method_source (~> 0.9.0)
@@ -39,10 +38,11 @@ GEM
39
38
  simplecov-html (0.10.2)
40
39
  sqlite3 (1.4.0)
41
40
  thread_safe (0.3.6)
42
- top_n_loader (1.0.0)
41
+ top_n_loader (1.0.1)
43
42
  activerecord
44
- tzinfo (1.2.5)
43
+ tzinfo (1.2.6)
45
44
  thread_safe (~> 0.1)
45
+ zeitwerk (2.2.2)
46
46
 
47
47
  PLATFORMS
48
48
  ruby
@@ -56,4 +56,4 @@ DEPENDENCIES
56
56
  sqlite3
57
57
 
58
58
  BUNDLED WITH
59
- 1.17.2
59
+ 2.1.2
data/README.md CHANGED
@@ -85,11 +85,11 @@ class Post < ActiveRecord::Base
85
85
  has_many :comments
86
86
  serializer_field :comments
87
87
  end
88
- ArSerializer.serialize Post.all, comments: [:id, params: { order: { id: :desc }, limit: 2 }]
88
+ ArSerializer.serialize Post.all, { comments: [:id, params: { order: { id: :desc }, limit: 2 }] }
89
89
 
90
90
  # context and params
91
91
  class Post < ActiveRecord::Base
92
- serializer_field :created_at do |context, params|
92
+ serializer_field :created_at do |context, **params|
93
93
  created_at.in_time_zone(context[:tz]).strftime params[:format]
94
94
  end
95
95
  end
@@ -123,10 +123,10 @@ class User < ActiveRecord::Base
123
123
  serializer_field :o_posts, association: :posts, only: :title
124
124
  serializer_field :e_posts, association: :posts, except: :comments
125
125
  end
126
- ArSerializer.serialize user, o_posts: :title, e_posts: :body
127
- ArSerializer.serialize user, o_posts: :*, e_posts: :*
128
- ArSerializer.serialize user, o_posts: :body #=> Error
129
- ArSerializer.serialize user, e_posts: :comments #=> Error
126
+ ArSerializer.serialize user, { o_posts: :title, e_posts: :body }
127
+ ArSerializer.serialize user, { o_posts: :*, e_posts: :* }
128
+ ArSerializer.serialize user, { o_posts: :body } #=> Error
129
+ ArSerializer.serialize user, { e_posts: :comments } #=> Error
130
130
 
131
131
  # types
132
132
  class User < ActiveRecord::Base
data/lib/ar_serializer.rb CHANGED
@@ -4,8 +4,8 @@ require 'ar_serializer/field'
4
4
  require 'active_record'
5
5
 
6
6
  module ArSerializer
7
- def self.serialize(*args)
8
- Serializer.serialize(*args)
7
+ def self.serialize(model, query, **option)
8
+ Serializer.serialize(model, query, **option)
9
9
  end
10
10
  end
11
11
 
@@ -50,7 +50,7 @@ module ArSerializer::Serializable
50
50
  namespaces = namespace.is_a?(Array) ? namespace : [namespace]
51
51
  namespaces.each do |ns|
52
52
  names.each do |name|
53
- field = ArSerializer::Field.create(self, association || name, option, &data_block)
53
+ field = ArSerializer::Field.create(self, association || name, **option, &data_block)
54
54
  _serializer_namespace(ns)[name.to_s] = field
55
55
  end
56
56
  end
@@ -64,8 +64,8 @@ module ArSerializer::Serializable
64
64
  _custom_preloaders[name] = block
65
65
  end
66
66
 
67
- def serializer_defaults(*args, &block)
68
- serializer_field :defaults, *args, &block
67
+ def serializer_defaults(**args, &block)
68
+ serializer_field :defaults, **args, &block
69
69
  end
70
70
  end
71
71
  end
@@ -1,4 +1,5 @@
1
1
  require 'ar_serializer/error'
2
+ require 'top_n_loader'
2
3
 
3
4
  class ArSerializer::Field
4
5
  attr_reader :includes, :preloaders, :data_block, :only, :except, :order_column
@@ -72,7 +73,7 @@ class ArSerializer::Field
72
73
 
73
74
  def validate_attributes(attributes)
74
75
  return unless @only || @except
75
- keys = attributes.keys.map(&:to_s) - ['*']
76
+ keys = attributes.map(&:first).map(&:to_s) - ['*']
76
77
  return unless (@only && (keys - @only).present?) || (@except && (keys & @except).present?)
77
78
  invalid_keys = [*(@only && keys - @only), *(@except && keys & @except)].uniq
78
79
  raise ArSerializer::InvalidQuery, "unpermitted attribute: #{invalid_keys}"
@@ -82,22 +83,12 @@ class ArSerializer::Field
82
83
  preloader = lambda do |models|
83
84
  klass.joins(association_name).where(id: models.map(&:id)).group(:id).count
84
85
  end
85
- data_block = lambda do |preloaded, _context, _params|
86
+ data_block = lambda do |preloaded, _context, **_params|
86
87
  preloaded[id] || 0
87
88
  end
88
89
  new preloaders: [preloader], data_block: data_block, type: :int
89
90
  end
90
91
 
91
- def self.top_n_loader_available?
92
- return @top_n_loader_available unless @top_n_loader_available.nil?
93
- @top_n_loader_available = begin
94
- require 'top_n_loader'
95
- true
96
- rescue LoadError
97
- nil
98
- end
99
- end
100
-
101
92
  def self.type_from_column_type(klass, name)
102
93
  type = type_from_attribute_type klass, name.to_s
103
94
  return :any if type.nil?
@@ -172,11 +163,11 @@ class ArSerializer::Field
172
163
  preloaders = []
173
164
  includes ||= name if klass.respond_to?(:reflect_on_association) && klass.reflect_on_association(name)
174
165
  end
175
- data_block ||= ->(preloaded, _context, _params) { preloaded[id] } if preloaders.size == 1
166
+ data_block ||= ->(preloaded, _context, **_params) { preloaded[id] } if preloaders.size == 1
176
167
  raise ArgumentError, 'data_block needed if multiple preloaders are present' if !preloaders.empty? && data_block.nil?
177
168
  new(
178
169
  includes: includes, preloaders: preloaders, only: only, except: except, order_column: order_column, type: type, params_type: params_type,
179
- data_block: data_block || ->(_context, _params) { send name }
170
+ data_block: data_block || ->(_context, **_params) { send name }
180
171
  )
181
172
  end
182
173
 
@@ -194,7 +185,7 @@ class ArSerializer::Field
194
185
  end
195
186
  info = klass._serializer_field_info(key)
196
187
  key = info&.order_column || key.to_s.underscore
197
- raise ArSerializer::InvalidQuery, "unpermitted order key: #{key}" unless klass.has_attribute?(key) && info
188
+ raise ArSerializer::InvalidQuery, "unpermitted order key: #{key}" unless klass.primary_key == key.to_s || (klass.has_attribute?(key) && info)
198
189
  raise ArSerializer::InvalidQuery, "invalid order mode: #{mode.inspect}" unless [:asc, :desc, 'asc', 'desc'].include? mode
199
190
  [key.to_sym, mode.to_sym]
200
191
  end
@@ -206,11 +197,11 @@ class ArSerializer::Field
206
197
  end
207
198
  params_type = { limit?: :int, order?: [{ :* => %w[asc desc] }, 'asc', 'desc'] }
208
199
  else
209
- preloader = lambda do |models, _context, _params|
200
+ preloader = lambda do |models, _context, **_params|
210
201
  preload_association klass, models, name
211
202
  end
212
203
  end
213
- data_block = lambda do |preloaded, _context, _params|
204
+ data_block = lambda do |preloaded, _context, **_params|
214
205
  preloaded ? preloaded[id] || [] : send(name)
215
206
  end
216
207
  new preloaders: [preloader], data_block: data_block, only: only, except: except, type: type, params_type: params_type
@@ -219,16 +210,14 @@ class ArSerializer::Field
219
210
  def self.preload_association(klass, models, name, limit: nil, order: nil)
220
211
  limit = limit&.to_i
221
212
  order_key, order_mode = parse_order klass.reflect_on_association(name).klass, order
222
- if limit && top_n_loader_available?
223
- return TopNLoader.load_associations klass, models.map(&:id), name, limit: limit, order: { order_key => order_mode }
224
- end
213
+ return TopNLoader.load_associations klass, models.map(&:id), name, limit: limit, order: { order_key => order_mode } if limit
225
214
  ActiveRecord::Associations::Preloader.new.preload models, name
226
- return if limit.nil? && order.nil?
215
+ return if order.nil?
227
216
  models.map do |model|
228
217
  records_nonnils, records_nils = model.send(name).partition(&order_key)
229
218
  records = records_nils.sort_by(&:id) + records_nonnils.sort_by { |r| [r[order_key], r.id] }
230
219
  records.reverse! if order_mode == :desc
231
- [model.id, limit ? records.take(limit) : records]
220
+ [model.id, records]
232
221
  end.to_h
233
222
  end
234
223
  end
@@ -9,8 +9,8 @@ class ArSerializer::GraphQL::Parser
9
9
  @chars = query.chars
10
10
  end
11
11
 
12
- def self.parse(*args)
13
- new(*args).parse
12
+ def self.parse(query, **option)
13
+ new(query, **option).parse
14
14
  end
15
15
 
16
16
  def parse
@@ -194,7 +194,7 @@ class ArSerializer::GraphQL::Parser
194
194
  args = parse_args
195
195
  consume_blank
196
196
  fields = parse_fields
197
- [name, { as: alias_name, params: args, attributes: fields }.compact]
197
+ [(alias_name || name), { field: name, params: args, attributes: fields }.compact]
198
198
  end
199
199
 
200
200
  def parse_fields
@@ -38,7 +38,15 @@ module ArSerializer::GraphQL
38
38
  type.collect_types types
39
39
  end
40
40
 
41
+ def args_required?
42
+ return false if field.arguments == :any
43
+ field.arguments.any? do |key, type|
44
+ !key.match?(/\?$/) && !(type.is_a?(Array) && type.include?(nil))
45
+ end
46
+ end
47
+
41
48
  def args_ts_type
49
+ return 'any' if field.arguments == :any
42
50
  arg_types = field.arguments.map do |key, type|
43
51
  "#{key}: #{TypeClass.from(type).ts_type}"
44
52
  end
@@ -37,9 +37,9 @@ module ArSerializer::Serializer
37
37
  Thread.current[:ar_serializer_current_namespaces] = namespaces_was
38
38
  end
39
39
 
40
- def self.serialize(model, args, context: nil, include_id: false, use: nil)
40
+ def self.serialize(model, query, context: nil, include_id: false, use: nil)
41
41
  with_namespaces use do
42
- attributes = parse_args(args)[:attributes]
42
+ attributes = parse_args(query)[:attributes]
43
43
  if model.is_a?(ArSerializer::Serializable)
44
44
  output = {}
45
45
  _serialize [[model, output]], attributes, context, include_id
@@ -59,21 +59,22 @@ module ArSerializer::Serializer
59
59
  next unless klass.respond_to? :_serializer_field_info
60
60
  models = value_outputs.map(&:first)
61
61
  value_outputs.each { |value, output| output[:id] = value.id } if include_id && klass.method_defined?(:id)
62
- if attributes[:*]
63
- all_keys = klass._serializer_field_keys.map(&:to_sym)
62
+ if attributes.any? { |k, _| k == :* }
63
+ all_keys = klass._serializer_field_keys.map(&:to_sym) - [:defaults]
64
64
  all_keys &= only.map(&:to_sym) if only
65
65
  all_keys -= except.map(&:to_sym) if except
66
- attributes = all_keys.map { |k| [k, {}] }.to_h.merge attributes
67
- attributes.delete :*
66
+ attributes = all_keys.map { |k| [k, {}] } + attributes.reject { |k, _| k == :* }
68
67
  end
69
- attributes.each_key do |name|
70
- field = klass._serializer_field_info name
71
- raise ArSerializer::InvalidQuery, "No serializer field `#{name}`#{" namespaces: #{current_namespaces}" if current_namespaces} for #{klass}" unless field
68
+ attributes.each do |name, sub_args|
69
+ field_name = sub_args[:field_name] || name
70
+ field = klass._serializer_field_info field_name
71
+ raise ArSerializer::InvalidQuery, "No serializer field `#{field_name}`#{" namespaces: #{current_namespaces}" if current_namespaces} for #{klass}" unless field
72
72
  ActiveRecord::Associations::Preloader.new.preload models, field.includes if field.includes.present?
73
73
  end
74
74
 
75
75
  preloader_params = attributes.flat_map do |name, sub_args|
76
- klass._serializer_field_info(name).preloaders.map do |p|
76
+ field_name = sub_args[:field_name] || name
77
+ klass._serializer_field_info(field_name).preloaders.map do |p|
77
78
  [p, sub_args[:params]]
78
79
  end
79
80
  end
@@ -84,9 +85,9 @@ module ArSerializer::Serializer
84
85
  preloader_values = preloader_params.compact.uniq.map do |key|
85
86
  preloader, params = key
86
87
  if preloader.arity < 0
87
- [key, preloader.call(models, context, params || {})]
88
+ [key, preloader.call(models, context, **(params || {}))]
88
89
  else
89
- [key, preloader.call(*[models, context, params || {}].take(preloader.arity))]
90
+ [key, preloader.call(*[models, context].take(preloader.arity), **(params || {}))]
90
91
  end
91
92
  end.to_h
92
93
 
@@ -102,11 +103,12 @@ module ArSerializer::Serializer
102
103
  params = sub_arg[:params]
103
104
  sub_calls = []
104
105
  column_name = sub_arg[:column_name] || name
105
- info = klass._serializer_field_info name
106
+ field_name = sub_arg[:field_name] || name
107
+ info = klass._serializer_field_info field_name
106
108
  preloadeds = info.preloaders.map { |p| preloader_values[[p, params]] } || []
107
109
  data_block = info.data_block
108
110
  value_outputs.each do |value, output|
109
- child = value.instance_exec(*preloadeds, context, params || {}, &data_block)
111
+ child = value.instance_exec(*preloadeds, context, **(params || {}), &data_block)
110
112
  if child.is_a?(Array) && child.all? { |el| el.is_a? ArSerializer::Serializable }
111
113
  output[column_name] = child.map do |record|
112
114
  data = {}
@@ -117,10 +119,6 @@ module ArSerializer::Serializer
117
119
  sub_output, record_elements = child.ar_serializer_build_sub_calls
118
120
  record_elements.each { |o| sub_calls << o }
119
121
  output[column_name] = sub_output
120
- elsif child.is_a? ArSerializer::CompositeValue
121
- sub_output, record_elements = child.build
122
- record_elements.each { |o| sub_calls << o }
123
- output[column_name] = sub_output
124
122
  elsif child.is_a? ArSerializer::Serializable
125
123
  data = {}
126
124
  sub_calls << [child, data]
@@ -151,27 +149,26 @@ module ArSerializer::Serializer
151
149
  end
152
150
 
153
151
  def self.parse_args(args, only_attributes: false)
154
- attributes = {}
152
+ attributes = []
155
153
  params = nil
156
154
  column_name = nil
155
+ field_name = nil
157
156
  (args.is_a?(Array) ? args : [args]).each do |arg|
158
157
  if arg.is_a?(Symbol) || arg.is_a?(String)
159
- attributes[arg.to_sym] = {}
158
+ attributes << [arg.to_sym, {}]
160
159
  elsif arg.is_a? Hash
161
160
  arg.each do |key, value|
162
161
  sym_key = key.to_sym
163
- if only_attributes
164
- attributes[sym_key] = value == true ? {} : parse_args(value)
165
- next
166
- end
167
- if sym_key == :as
162
+ if !only_attributes && sym_key == :field
163
+ field_name = value
164
+ elsif !only_attributes && sym_key == :as
168
165
  column_name = value
169
- elsif sym_key == :attributes
170
- attributes.update parse_args(value, only_attributes: true)
171
- elsif sym_key == :params
166
+ elsif !only_attributes && %i[attributes query].include?(sym_key)
167
+ attributes.concat parse_args(value, only_attributes: true)
168
+ elsif !only_attributes && sym_key == :params
172
169
  params = deep_with_indifferent_access value
173
170
  else
174
- attributes[sym_key] = value == true ? {} : parse_args(value)
171
+ attributes << [sym_key, value == true ? {} : parse_args(value)]
175
172
  end
176
173
  end
177
174
  else
@@ -179,6 +176,6 @@ module ArSerializer::Serializer
179
176
  end
180
177
  end
181
178
  return attributes if only_attributes
182
- { attributes: attributes, column_name: column_name, params: params || {} }
179
+ { attributes: attributes, column_name: column_name, field_name: field_name, params: params || {} }
183
180
  end
184
181
  end
@@ -4,32 +4,60 @@ module ArSerializer::TypeScript
4
4
  def self.generate_type_definition(*classes)
5
5
  types = related_serializer_types classes.flatten
6
6
  [
7
+ 'type NonAliasQuery = true | string | string[] | ({ field?: undefined } & { [key: string]: any })',
7
8
  types.map { |t| data_type_definition t },
8
9
  types.map { |t| query_type_definition t }
9
10
  ].join "\n"
10
11
  end
11
12
 
13
+ FieldInfo = Struct.new :name, :params_required?, :params_type, :query_type, :sub_query_params
14
+
12
15
  def self.query_type_definition(type)
13
16
  field_definitions = type.fields.map do |field|
14
17
  association_type = field.type.association_type
15
- if association_type
16
- qname = "Type#{association_type.name}Query"
17
- if field.args.empty?
18
- "#{field.name}?: true | #{qname} | { as?: string; attributes?: #{qname} }"
19
- else
20
- "#{field.name}?: true | #{qname} | { as?: string; params: #{field.args_ts_type}; attributes?: #{qname} }"
21
- end
22
- else
23
- "#{field.name}?: true | { as: string }"
24
- end
18
+ query_type = "Type#{association_type.name}Query" if association_type
19
+ params_type = field.args_ts_type unless field.args.empty?
20
+ params_required = field.args_required?
21
+ attrs = []
22
+ attrs << "query?: #{query_type}" if query_type
23
+ attrs << "params#{'?' unless params_required}: #{params_type}" if params_type
24
+ sub_query_params = attrs
25
+ FieldInfo.new field.name, params_required, params_type, query_type, sub_query_params
25
26
  end
26
- field_definitions << "'*'?: true"
27
+ accept_wildcard = !field_definitions.any?(&:params_required?)
27
28
  query_type_name = "Type#{type.name}Query"
29
+ standalone_fields_name = "Type#{type.name}StandaloneFields"
30
+ alias_query_type_name = "Type#{type.name}AliasFieldQuery"
28
31
  base_query_type_name = "Type#{type.name}QueryBase"
32
+ standalone_fields_definition = field_definitions.reject(&:params_required?).map do |info|
33
+ "'#{info.name}'"
34
+ end.join(' | ')
35
+ standalone_fields_definition += " | '*'" if accept_wildcard
36
+ alias_query_type_definition = field_definitions.map do |info|
37
+ attrs = ["field: '#{info.name}'", *info.sub_query_params].join('; ')
38
+ " | { #{attrs} }\n"
39
+ end.join
40
+ base_query_type_definition = field_definitions.map do |info|
41
+ types = []
42
+ unless info.params_required?
43
+ types << true
44
+ types << info.query_type if info.query_type
45
+ end
46
+ types << "{ field: never; #{info.sub_query_params.join('; ')} }" unless info.sub_query_params.empty?
47
+ " #{info.name}: #{types.join(' | ')}"
48
+ end.join("\n")
49
+ base_query_type_definition += "\n '*': true" if accept_wildcard
29
50
  <<~TYPE
30
- export type #{query_type_name} = keyof (#{base_query_type_name}) | Readonly<(keyof (#{base_query_type_name}))[]> | #{base_query_type_name}
51
+ export type #{query_type_name} = #{standalone_fields_name} | Readonly<#{standalone_fields_name}[]>
52
+ | (
53
+ { [key in keyof #{base_query_type_name}]?: key extends '*' ? true : #{base_query_type_name}[key] | #{alias_query_type_name} }
54
+ & { [key: string]: #{alias_query_type_name} | NonAliasQuery }
55
+ )
56
+ export type #{standalone_fields_name} = #{standalone_fields_definition.presence || 'never'}
57
+ export type #{alias_query_type_name} =
58
+ #{alias_query_type_definition.presence || 'never'}
31
59
  export interface #{base_query_type_name} {
32
- #{field_definitions.map { |line| " #{line}" }.join("\n")}
60
+ #{base_query_type_definition}
33
61
  }
34
62
  TYPE
35
63
  end
@@ -1,3 +1,3 @@
1
1
  module ArSerializer
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_serializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tompng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-11 00:00:00.000000000 Z
11
+ date: 2020-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  - !ruby/object:Gem::Version
154
154
  version: '0'
155
155
  requirements: []
156
- rubygems_version: 3.0.1
156
+ rubygems_version: 3.1.2
157
157
  signing_key:
158
158
  specification_version: 4
159
159
  summary: ActiveRecord serializer, avoid N+1