simple_ams 0.2.1 → 0.2.6

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +28 -0
  3. data/.rubocop.yml +56 -0
  4. data/CHANGELOG.md +22 -0
  5. data/Gemfile +2 -2
  6. data/README.md +665 -116
  7. data/Rakefile +3 -3
  8. data/bin/console +3 -3
  9. data/lib/simple_ams.rb +34 -33
  10. data/lib/simple_ams/adapters/ams.rb +26 -32
  11. data/lib/simple_ams/adapters/jsonapi.rb +47 -64
  12. data/lib/simple_ams/document.rb +38 -37
  13. data/lib/simple_ams/document/fields.rb +36 -37
  14. data/lib/simple_ams/document/forms.rb +7 -9
  15. data/lib/simple_ams/document/generics.rb +35 -37
  16. data/lib/simple_ams/document/links.rb +7 -9
  17. data/lib/simple_ams/document/metas.rb +7 -11
  18. data/lib/simple_ams/document/primary_id.rb +14 -17
  19. data/lib/simple_ams/document/relations.rb +99 -109
  20. data/lib/simple_ams/dsl.rb +73 -71
  21. data/lib/simple_ams/methy.rb +2 -2
  22. data/lib/simple_ams/options.rb +267 -265
  23. data/lib/simple_ams/options/adapter.rb +2 -2
  24. data/lib/simple_ams/options/concerns/filterable.rb +29 -34
  25. data/lib/simple_ams/options/concerns/mod.rb +4 -0
  26. data/lib/simple_ams/options/concerns/name_value_hash.rb +25 -26
  27. data/lib/simple_ams/options/concerns/tracked_properties.rb +15 -17
  28. data/lib/simple_ams/options/concerns/value_hash.rb +25 -26
  29. data/lib/simple_ams/options/fields.rb +1 -1
  30. data/lib/simple_ams/options/forms.rb +1 -2
  31. data/lib/simple_ams/options/generics.rb +2 -4
  32. data/lib/simple_ams/options/includes.rb +1 -1
  33. data/lib/simple_ams/options/links.rb +1 -1
  34. data/lib/simple_ams/options/metas.rb +1 -1
  35. data/lib/simple_ams/options/primary_id.rb +1 -1
  36. data/lib/simple_ams/options/relations.rb +9 -7
  37. data/lib/simple_ams/options/type.rb +1 -2
  38. data/lib/simple_ams/renderer.rb +43 -41
  39. data/lib/simple_ams/version.rb +1 -1
  40. data/simple_ams.gemspec +17 -17
  41. metadata +30 -27
  42. data/.travis.yml +0 -5
@@ -1,4 +1,4 @@
1
- require "simple_ams"
1
+ require 'simple_ams'
2
2
 
3
3
  module SimpleAMS::DSL
4
4
  def self.included(host_class)
@@ -17,7 +17,7 @@ module SimpleAMS::DSL
17
17
  links: links,
18
18
  metas: metas,
19
19
  forms: forms,
20
- generics: generics,
20
+ generics: generics
21
21
  }
22
22
  end
23
23
  end
@@ -26,13 +26,13 @@ module SimpleAMS::DSL
26
26
  end
27
27
 
28
28
  module ClassMethods
29
- #TODO: Shouldn't we call here super to presever user's behavior ?
29
+ # TODO: Shouldn't we call here super to presever user's behavior ?
30
30
  def inherited(subclass)
31
31
  subclass.with_options(
32
32
  options.merge(
33
- #TODO: maybe add another group of elements under dsl?
34
- #this could be DSL::Type.new(type).explicit?
35
- type[-1][:_explicit] ? {} : {type: nil}
33
+ # TODO: maybe add another group of elements under dsl?
34
+ # this could be DSL::Type.new(type).explicit?
35
+ type[-1][:_explicit] ? {} : { type: nil }
36
36
  )
37
37
  )
38
38
 
@@ -49,16 +49,16 @@ module SimpleAMS::DSL
49
49
  links: links,
50
50
  metas: metas,
51
51
  forms: forms,
52
- generics: generics,
52
+ generics: generics
53
53
  }
54
54
  end
55
55
  end
56
56
 
57
57
  _klass.with_options(
58
58
  self::Collection_.options.merge(
59
- #TODO: maybe add another group of elements under dsl?
60
- #this could be DSL::Type.new(type).explicit?
61
- type[-1][:_explicit] ? {} : {type: nil}
59
+ # TODO: maybe add another group of elements under dsl?
60
+ # this could be DSL::Type.new(type).explicit?
61
+ type[-1][:_explicit] ? {} : { type: nil }
62
62
  )
63
63
  )
64
64
  subclass.const_set('Collection_', _klass)
@@ -72,47 +72,46 @@ module SimpleAMS::DSL
72
72
  }
73
73
  end
74
74
 
75
- #TODO: Add tests !!
75
+ # TODO: Add tests !!
76
76
  def _default_type_name
77
- if self.to_s.end_with?('::Collection_')
78
- _name = self.to_s.gsub(
79
- 'Serializer',''
77
+ if to_s.end_with?('::Collection_')
78
+ _name = to_s.gsub(
79
+ 'Serializer', ''
80
80
  ).gsub(
81
81
  '::Collection_', ''
82
82
  ).downcase.split('::')[-1]
83
83
 
84
- return "#{_name}_collection".to_sym
84
+ "#{_name}_collection".to_sym
85
85
  else
86
- return self.to_s.gsub('Serializer','').downcase.split('::')[-1].to_sym
86
+ to_s.gsub('Serializer', '').downcase.split('::')[-1].to_sym
87
87
  end
88
88
  end
89
+
89
90
  def with_options(options = {})
90
91
  @_options = options
91
92
  meths = SimpleAMS::DSL::ClassMethods.instance_methods(false)
92
93
  @_options.each do |key, value|
93
94
  if key == :relations
94
- (value || []).each{|rel_value|
95
+ (value || []).each do |rel_value|
95
96
  append_relationship(rel_value)
96
- }
97
- elsif key.to_sym == :collection
98
- #TODO: Add proc option maybe?
99
- if value.is_a?(Hash)
100
- collection{}.with_options(value)
101
97
  end
98
+ elsif key.to_sym == :collection
99
+ # TODO: Add proc option maybe?
100
+ collection {}.with_options(value) if value.is_a?(Hash)
102
101
  elsif meths.include?(key)
103
102
  if (value.is_a?(Array) && value[0].is_a?(Array)) || value.is_a?(Hash)
104
- self.send(key, value)
103
+ send(key, value)
105
104
  else
106
- self.send(key, *value)
105
+ send(key, *value)
107
106
  end
108
107
  else
109
108
  SimpleAMS.configuration.logger.info(
110
- "SimpeAMS: #{key} is not recognized, ignoring (from #{self.to_s})"
109
+ "SimpeAMS: #{key} is not recognized, ignoring (from #{self})"
111
110
  )
112
111
  end
113
112
  end
114
113
 
115
- return @_options
114
+ @_options
116
115
  end
117
116
 
118
117
  def adapter(value = nil, options = {})
@@ -129,7 +128,7 @@ module SimpleAMS::DSL
129
128
 
130
129
  def attributes(*args)
131
130
  @_attributes ||= []
132
- return @_attributes.uniq if (args&.empty? || args.nil?)
131
+ return @_attributes.uniq if args&.empty? || args.nil?
133
132
 
134
133
  append_attributes(args)
135
134
  end
@@ -167,20 +166,20 @@ module SimpleAMS::DSL
167
166
  def embedded_class_for(name, options, block)
168
167
  embedded = Class.new(self)
169
168
  klass_name = "Embedded#{name.to_s.capitalize}Options_"
170
- self.const_set(klass_name, embedded)
169
+ const_set(klass_name, embedded)
171
170
  embedded.with_options(
172
- default_options.merge(options.select{|k| k != :serializer})
171
+ default_options.merge(options.reject { |k| k == :serializer })
173
172
  )
174
173
  embedded.instance_exec(&block) if block
175
174
 
176
- return embedded
175
+ embedded
177
176
  end
178
177
 
179
- #TODO: there is no memoization here, hence we ignore includes manually set !!
180
- #Consider fixing it by employing an observer that will clean the instance var
181
- #each time @_relations is updated
182
- def includes(*args)
183
- relations.map{|rel| rel[1] }
178
+ # TODO: there is no memoization here, hence we ignore includes manually set !!
179
+ # Consider fixing it by employing an observer that will clean the instance var
180
+ # each time @_relations is updated
181
+ def includes(*_args)
182
+ relations.map { |rel| rel[1] }
184
183
  end
185
184
 
186
185
  def link(name, value, options = {})
@@ -201,7 +200,8 @@ module SimpleAMS::DSL
201
200
 
202
201
  def links(links = [])
203
202
  return @_links ||= [] if links.empty?
204
- links.map{|key, value| append_link([key, value].flatten(1))} if links.is_a?(Hash)
203
+
204
+ links.map { |key, value| append_link([key, value].flatten(1)) } if links.is_a?(Hash)
205
205
 
206
206
  @_links ||= links
207
207
  end
@@ -209,21 +209,23 @@ module SimpleAMS::DSL
209
209
  def metas(metas = [])
210
210
  return @_metas ||= [] if metas.empty?
211
211
 
212
- metas.map{|key, value| append_meta([key, value].flatten(1))} if metas.is_a?(Hash)
212
+ metas.map { |key, value| append_meta([key, value].flatten(1)) } if metas.is_a?(Hash)
213
213
 
214
214
  @_metas ||= metas
215
215
  end
216
216
 
217
217
  def forms(forms = [])
218
218
  return @_forms ||= [] if forms.empty?
219
- forms.map{|key, value| append_form([key, value].flatten(1))} if forms.is_a?(Hash)
219
+
220
+ forms.map { |key, value| append_form([key, value].flatten(1)) } if forms.is_a?(Hash)
220
221
 
221
222
  @_forms ||= forms
222
223
  end
223
224
 
224
225
  def generics(generics = [])
225
226
  return @_generics ||= [] if generics.empty?
226
- generics.map{|key, value| append_generic([key, value].flatten(1))} if generics.is_a?(Hash)
227
+
228
+ generics.map { |key, value| append_generic([key, value].flatten(1)) } if generics.is_a?(Hash)
227
229
 
228
230
  @_generics ||= generics
229
231
  end
@@ -237,7 +239,7 @@ module SimpleAMS::DSL
237
239
 
238
240
  self::Collection_.type(name) if name
239
241
 
240
- return self::Collection_
242
+ self::Collection_
241
243
  end
242
244
 
243
245
  def options
@@ -261,50 +263,50 @@ module SimpleAMS::DSL
261
263
  end
262
264
 
263
265
  private
264
- def _value_hash_for(current, value, options, name)
265
- _type = current || default_options[name]
266
- return _type if value.nil?
267
266
 
268
- return [value, options]
269
- end
267
+ def _value_hash_for(current, value, options, name)
268
+ _type = current || default_options[name]
269
+ return _type if value.nil?
270
270
 
271
- def append_relationship(rel)
272
- @_relations ||= []
271
+ [value, options]
272
+ end
273
273
 
274
- @_relations << rel
275
- end
274
+ def append_relationship(rel)
275
+ @_relations ||= []
276
276
 
277
- def append_attributes(*attrs)
278
- @_attributes ||= []
277
+ @_relations << rel
278
+ end
279
279
 
280
- @_attributes = (@_attributes << attrs).flatten.compact.uniq
281
- end
280
+ def append_attributes(*attrs)
281
+ @_attributes ||= []
282
282
 
283
- def append_link(link)
284
- @_links ||= []
283
+ @_attributes = (@_attributes << attrs).flatten.compact.uniq
284
+ end
285
285
 
286
- @_links << link
287
- end
286
+ def append_link(link)
287
+ @_links ||= []
288
288
 
289
- def append_meta(meta)
290
- @_metas ||= []
289
+ @_links << link
290
+ end
291
291
 
292
- @_metas << meta
293
- end
292
+ def append_meta(meta)
293
+ @_metas ||= []
294
+
295
+ @_metas << meta
296
+ end
294
297
 
295
- def append_form(form)
296
- @_forms ||= []
298
+ def append_form(form)
299
+ @_forms ||= []
297
300
 
298
- @_forms << form
299
- end
301
+ @_forms << form
302
+ end
300
303
 
301
- def append_generic(generic)
302
- @_generics ||= []
304
+ def append_generic(generic)
305
+ @_generics ||= []
303
306
 
304
- @_generics << generic
305
- end
307
+ @_generics << generic
308
+ end
306
309
 
307
- def empty_options
308
- end
310
+ def empty_options; end
309
311
  end
310
312
  end
@@ -2,9 +2,9 @@ module SimpleAMS::Methy
2
2
  def self.of(hash = {})
3
3
  m = Module.new
4
4
  hash.each do |key, value|
5
- m.send(:define_method, key){ value }
5
+ m.send(:define_method, key) { value }
6
6
  end
7
7
 
8
- return m
8
+ m
9
9
  end
10
10
  end
@@ -1,333 +1,335 @@
1
- require "simple_ams"
1
+ require 'simple_ams'
2
2
 
3
- module SimpleAMS
4
- class Options
5
- include Concerns::TrackedProperties
3
+ class SimpleAMS::Options
4
+ include Concerns::TrackedProperties
6
5
 
7
- class Collection < self; end
6
+ class Collection < self; end
8
7
 
9
- attr_reader :resource, :allowed_options, :injected_options
8
+ attr_reader :resource, :allowed_options, :injected_options
10
9
 
11
- #injected_options is always a Hash object
12
- def initialize(resource = nil, injected_options: {}, allowed_options: nil)
13
- initialize_tracking!
14
- @resource = resource
15
- @injected_options = injected_options || {}
16
- @_internal = @injected_options[:_internal] || {}
17
- @allowed_options = allowed_options || fetch_allowed_options
18
- end
19
- alias collection resource
10
+ # injected_options is always a Hash object
11
+ def initialize(resource = nil, injected_options: {}, allowed_options: nil)
12
+ initialize_tracking!
13
+ @resource = resource
14
+ @injected_options = injected_options || {}
15
+ @_internal = @injected_options[:_internal] || {}
16
+ @allowed_options = allowed_options || fetch_allowed_options
17
+ end
18
+ alias collection resource
20
19
 
21
- #performance enchancement method for non-polymorphic collections
22
- def with_resource(resource)
23
- @resource = resource
20
+ # performance enchancement method for non-polymorphic collections
21
+ def with_resource(resource)
22
+ @resource = resource
23
+ remove_instance_variable(:@serializer) if defined?(@serializer)
24
+ clean_volatile_properties!
24
25
 
25
- clean_volatile_properties!
26
+ self
27
+ end
26
28
 
27
- return self
28
- end
29
+ def relation_options_for(relation_name)
30
+ _relation_options[relation_name] || {}
31
+ end
29
32
 
30
- def relation_options_for(relation_name)
31
- return _relation_options[relation_name] || {}
32
- end
33
+ def primary_id
34
+ return tracked(:primary_id).value if tracked(:primary_id).value
33
35
 
34
- def primary_id
35
- return tracked(__method__).value if tracked(__method__).value
36
+ tracked(:primary_id).value = array_of_value_hash_for(PrimaryId, :primary_id)
37
+ end
36
38
 
37
- return tracked(__method__).value = array_of_value_hash_for(PrimaryId, :primary_id)
38
- end
39
+ def type
40
+ return tracked(:type).value if tracked(:type).value
39
41
 
40
- def type
41
- return tracked(__method__).value if tracked(__method__).value
42
+ tracked(:type).value = array_of_value_hash_for(Type, :type)
43
+ end
42
44
 
43
- return tracked(__method__).value = array_of_value_hash_for(Type, :type)
44
- end
45
+ def name
46
+ @name ||= injected_options[:name] || allowed_options[:name] || type.name
47
+ end
45
48
 
46
- def name
47
- @name ||= injected_options[:name] || allowed_options[:name] || type.name
48
- end
49
+ # TODO: optimize for nested fields?
50
+ def fields
51
+ return @fields if defined?(@fields)
49
52
 
50
- #TODO: optimize for nested fields?
51
- def fields
52
- return @fields if defined?(@fields)
53
+ @fields = array_of_items_for(Fields, :fields)
54
+ end
53
55
 
54
- return @fields = array_of_items_for(Fields, :fields)
55
- end
56
+ def includes
57
+ return @includes if defined?(@includes)
56
58
 
57
- def includes
58
- return @includes if defined?(@includes)
59
+ @includes = array_of_items_for(Includes, :includes)
60
+ end
59
61
 
60
- return @includes = array_of_items_for(Includes, :includes)
61
- end
62
+ # TODO: correctly loop over injected relations, although should be a rarely used feature
63
+ def relations
64
+ return @relations if defined?(@relations)
62
65
 
63
- #TODO: correctly loop over injected relations, although should be a rarely used feature
64
- def relations
65
- return @relations if defined?(@relations)
66
+ relations = injected_options.fetch(:relations, nil)
67
+ relations = allowed_options.fetch(:relations, []) if relations.nil?
66
68
 
67
- relations = injected_options.fetch(:relations, nil)
68
- relations = allowed_options.fetch(:relations, []) if relations.nil?
69
+ @relations = Relations.new(relations, includes)
70
+ end
69
71
 
70
- return @relations = Relations.new(relations, includes)
71
- end
72
+ def links
73
+ return tracked(:links).value if tracked(:links).value
72
74
 
73
- def links
74
- return tracked(__method__).value if tracked(__method__).value
75
+ tracked(:links).value = array_of_name_value_hash_for(Links, Links::Link, :links)
76
+ end
75
77
 
76
- return tracked(__method__).value = array_of_name_value_hash_for(Links, Links::Link, :links)
77
- end
78
+ def metas
79
+ return tracked(:metas).value if tracked(:metas).value
78
80
 
79
- def metas
80
- return tracked(__method__).value if tracked(__method__).value
81
+ tracked(:metas).value = array_of_name_value_hash_for(Metas, Metas::Meta, :metas)
82
+ end
81
83
 
82
- return tracked(__method__).value = array_of_name_value_hash_for(Metas, Metas::Meta, :metas)
83
- end
84
+ def forms
85
+ return tracked(:forms).value if tracked(:forms).value
84
86
 
85
- def forms
86
- return tracked(__method__).value if tracked(__method__).value
87
+ tracked(:forms).value = array_of_name_value_hash_for(Forms, Forms::Form, :forms)
88
+ end
87
89
 
88
- return tracked(__method__).value = array_of_name_value_hash_for(Forms, Forms::Form, :forms)
89
- end
90
+ def generics
91
+ return tracked(:generics).value if tracked(:generics).value
90
92
 
91
- def generics
92
- return tracked(__method__).value if tracked(__method__).value
93
+ tracked(:generics).value = array_of_name_value_hash_for(
94
+ Generics, Generics::Option, :generics
95
+ )
96
+ end
93
97
 
94
- return tracked(__method__).value = array_of_name_value_hash_for(
95
- Generics, Generics::Option, :generics
96
- )
97
- end
98
+ # TODO: handle case of proc
99
+ def serializer
100
+ return @serializer if defined?(@serializer)
98
101
 
99
- #TODO: handle case of proc
100
- def serializer
101
- return @serializer if defined?(@serializer)
102
+ _serializer = injected_options.fetch(:serializer, serializer_class)
102
103
 
103
- _serializer = injected_options.fetch(:serializer, serializer_class)
104
+ @serializer = instantiated_serializer_for(_serializer)
105
+ end
104
106
 
105
- return @serializer = instantiated_serializer_for(_serializer)
106
- end
107
+ def adapter(_serializer: nil)
108
+ return @adapter if defined?(@adapter) && _serializer.nil?
107
109
 
108
- def adapter(_serializer: nil)
109
- return @adapter if defined?(@adapter) && _serializer.nil?
110
- serializer = _serializer || serializer
110
+ serializer = _serializer || serializer
111
111
 
112
- @adapter = Adapter.new(*injected_options.fetch(:adapter, [nil]), {
112
+ @adapter = Adapter.new(
113
+ *injected_options.fetch(:adapter, [nil]),
114
+ resource: resource, serializer: serializer
115
+ )
116
+ if @adapter.value.nil?
117
+ @adapter = Adapter.new(
118
+ *allowed_options.fetch(:adapter, [nil]),
113
119
  resource: resource, serializer: serializer
114
- })
115
- if @adapter.value.nil?
116
- @adapter = Adapter.new(*allowed_options.fetch(:adapter, [nil]), {
117
- resource: resource, serializer: serializer
118
- })
119
- end
120
- =begin
121
- if @adapter.value.nil?
122
- @adapter = Adapter.new(SimpleAMS::Adapters::AMS, {
123
- resource: resource, serializer: serializer
124
- })
125
- end
126
- =end
127
-
128
- return @adapter
120
+ )
129
121
  end
122
+ # if @adapter.value.nil?
123
+ # @adapter = Adapter.new(SimpleAMS::Adapters::AMS, {
124
+ # resource: resource, serializer: serializer
125
+ # })
126
+ # end
130
127
 
131
- # the following should be the same for all (nested) serializers of the same document
132
- def expose
133
- @expose ||= injected_options.fetch(:expose, {})
134
- end
128
+ @adapter
129
+ end
135
130
 
136
- def as_hash
137
- {
138
- adapter: adapter.raw,
139
- primary_id: primary_id.raw,
140
- type: type.raw,
141
- name: name,
142
- fields: fields.raw,
143
- serializer: serializer_class,
144
- #relations: relations.raw, #TODO: why have I commented that out ?
145
- includes: includes.raw,
146
- links: links.raw,
147
- metas: metas.raw,
148
- expose: expose,
149
- _internal: _internal
150
- }
151
- end
131
+ # the following should be the same for all (nested) serializers of the same document
132
+ def expose
133
+ @expose ||= injected_options.fetch(:expose, {})
134
+ end
152
135
 
153
- def collection_options
154
- return @collection_options if defined?(@collection_options)
155
-
156
- #TODO: Do we need that merge ?
157
- _injected_options = @injected_options.fetch(:collection, {}).merge({
158
- serializer: collection_serializer_class,
159
- adapter: adapter(_serializer: collection_serializer_class).raw,
160
- expose: expose
161
- })
162
- _allowed_options = @allowed_options.fetch(:collection).options
163
-
164
- return @collection_options = self.class::Collection.new(
165
- resource,
166
- injected_options: _injected_options,
167
- allowed_options: _allowed_options
168
- )
169
- end
136
+ def as_hash
137
+ {
138
+ adapter: adapter.raw,
139
+ primary_id: primary_id.raw,
140
+ type: type.raw,
141
+ name: name,
142
+ fields: fields.raw,
143
+ serializer: serializer_class,
144
+ # relations: relations.raw, #TODO: why have I commented that out ?
145
+ includes: includes.raw,
146
+ links: links.raw,
147
+ metas: metas.raw,
148
+ expose: expose,
149
+ _internal: _internal
150
+ }
151
+ end
170
152
 
171
- def serializer_class
172
- return @serializer_class if defined?(@serializer_class)
153
+ def collection_options
154
+ return @collection_options if defined?(@collection_options)
155
+
156
+ # TODO: Do we need that merge ?
157
+ _injected_options = @injected_options.fetch(:collection, {}).merge({
158
+ serializer: collection_serializer_class,
159
+ adapter: adapter(_serializer: collection_serializer_class).raw,
160
+ expose: expose
161
+ })
162
+ _allowed_options = @allowed_options.fetch(:collection).options
163
+
164
+ @collection_options = self.class::Collection.new(
165
+ resource,
166
+ injected_options: _injected_options,
167
+ allowed_options: _allowed_options
168
+ )
169
+ end
173
170
 
174
- @serializer_class = injected_options.fetch(:serializer, nil)
171
+ def serializer_class
172
+ return @serializer_class if defined?(@serializer_class)
175
173
 
176
- return @serializer_class if @serializer_class
174
+ @serializer_class = injected_options.fetch(:serializer, nil)
177
175
 
178
- return @serializer_class = infer_serializer
179
- end
176
+ return @serializer_class if @serializer_class
177
+
178
+ @serializer_class = infer_serializer
179
+ end
180
180
 
181
- #TODO: maybe have that inside :collection? (isomorphism)
182
- def collection_serializer_class
183
- return @collection_serializer_class if defined?(@collection_serializer_class)
181
+ # TODO: maybe have that inside :collection? (isomorphism)
182
+ def collection_serializer_class
183
+ return @collection_serializer_class if defined?(@collection_serializer_class)
184
184
 
185
- if serializer_class.is_a?(Proc) #TODO: maybe we should do duck typing instead?
186
- @collection_serializer_class = injected_options[:collection_serializer]
187
- if @collection_serializer_class.nil?
188
- raise "In case of a proc serializer, you need to specify a collection_serializer"
189
- end
190
- else
191
- @collection_serializer_class = serializer_class
185
+ if serializer_class.is_a?(Proc) # TODO: maybe we should do duck typing instead?
186
+ @collection_serializer_class = injected_options[:collection_serializer]
187
+ if @collection_serializer_class.nil?
188
+ raise 'In case of a proc serializer, you need to specify a collection_serializer'
192
189
  end
193
-
194
- return @collection_serializer_class
190
+ else
191
+ @collection_serializer_class = serializer_class
195
192
  end
196
193
 
197
- private
198
- attr_reader :_internal
199
-
200
- #TODO: add method-based links, should boost performance
201
- def array_of_name_value_hash_for(collection_klass, item_klass, name)
202
- injected = injected_options.fetch(name, nil)
203
- if injected
204
- injected = collection_klass.new(
205
- injected.map{|l| item_klass.new(*l.flatten, {
206
- resource: resource, serializer: serializer
207
- })}
194
+ @collection_serializer_class
195
+ end
196
+
197
+ private
198
+
199
+ attr_reader :_internal
200
+
201
+ # TODO: add method-based links, should boost performance
202
+ def array_of_name_value_hash_for(collection_klass, item_klass, name)
203
+ injected = injected_options.fetch(name, nil)
204
+ if injected
205
+ injected = collection_klass.new(
206
+ injected.map do |l|
207
+ item_klass.new(
208
+ *l.flatten,
209
+ resource: resource, serializer: serializer
208
210
  )
209
211
  end
212
+ )
213
+ end
210
214
 
211
- allowed = collection_klass.new(
212
- allowed_options.fetch(name).map{|l| item_klass.new(*l, {
213
- resource: resource, serializer: serializer
214
- })}
215
+ allowed = collection_klass.new(
216
+ allowed_options.fetch(name).map do |l|
217
+ item_klass.new(
218
+ *l,
219
+ resource: resource, serializer: serializer
215
220
  )
216
-
217
- return collection_klass.new(priority_options_for(
218
- #TODO: correctly loop over injected properties
219
- injected: injected,
220
- allowed: allowed,
221
- ).uniq{|item| item.name})
222
221
  end
222
+ )
223
223
 
224
- def array_of_value_hash_for(klass, name)
225
- _options = injected_options.fetch(name, nil)
226
- _options = allowed_options.fetch(name, nil) unless _options
224
+ collection_klass.new(priority_options_for(
225
+ # TODO: correctly loop over injected properties
226
+ injected: injected,
227
+ allowed: allowed
228
+ ).uniq(&:name))
229
+ end
227
230
 
228
- return klass.new(*_options, {
229
- resource: resource, serializer: serializer
230
- })
231
- end
231
+ def array_of_value_hash_for(klass, name)
232
+ _options = injected_options.fetch(name, nil)
233
+ _options ||= allowed_options.fetch(name, nil)
232
234
 
233
- def array_of_items_for(klass, name)
234
- injected = injected_options.fetch(name, nil)
235
+ klass.new(
236
+ *_options,
237
+ resource: resource, serializer: serializer
238
+ )
239
+ end
235
240
 
236
- if injected.nil?
237
- return klass.new(allowed_options.fetch(name).uniq)
238
- else
239
- return klass.new(priority_options_for(
240
- injected: klass.new(injected_options.fetch(name, nil)),
241
- allowed: klass.new(allowed_options.fetch(name).uniq)
242
- ).uniq)
243
- end
244
- end
241
+ def array_of_items_for(klass, name)
242
+ injected = injected_options.fetch(name, nil)
245
243
 
246
- def priority_options_for(allowed:, injected:)
247
- if not injected.nil?
248
- allowed = injected.class.new(
249
- injected.map{|s| s.is_a?(Hash) ? (s.first && s.first[0]) : s}
250
- ) & allowed
251
- end
244
+ if injected.nil?
245
+ klass.new(allowed_options.fetch(name).uniq)
246
+ else
247
+ klass.new(priority_options_for(
248
+ injected: klass.new(injected_options.fetch(name, nil)),
249
+ allowed: klass.new(allowed_options.fetch(name).uniq)
250
+ ).uniq)
251
+ end
252
+ end
252
253
 
253
- return allowed
254
- end
254
+ def priority_options_for(allowed:, injected:)
255
+ unless injected.nil?
256
+ allowed = injected.class.new(
257
+ injected.map { |s| s.is_a?(Hash) ? s.keys : s }.flatten
258
+ ) & allowed
259
+ end
255
260
 
256
- =begin
257
- def options_for(allowed:, injected:)
258
- (allowed || []).concat(injected || [])
259
- end
260
- =end
261
-
262
- def _relation_options
263
- return @_relation_options if defined?(@_relation_options)
264
-
265
- @_relation_options = relations.inject({}){|memo, relation|
266
- includes_value = (injected_options[:includes] || {}).find{|incl_hash|
267
- incl_hash.is_a?(Hash) &&
268
- (incl_hash.first && incl_hash.first[0]).to_s == relation.name.to_s
269
- }
270
- if includes_value
271
- includes_value = includes_value[relation.name]
272
- else
273
- #it's important here to return empty array if nothing is found..
274
- includes_value = []
275
- end
276
-
277
- fields_value = (injected_options[:fields] || {}).find{|field_hash|
278
- field_hash.is_a?(Hash) &&
279
- (field_hash.first && field_hash.first[0]).to_s == relation.name.to_s
280
- }
281
-
282
- #.. while here just nil will work (pick default fields from serializer)
283
- fields_value = fields_value[relation.name] if fields_value
284
-
285
- memo[relation.name] = {
286
- includes: includes_value,
287
- fields: fields_value
288
- }
289
- memo
290
- }
291
- end
261
+ allowed
262
+ end
292
263
 
293
- #TODO: raise exception if both are nil!
294
- def fetch_allowed_options
295
- _serializer_class = self.serializer_class
296
- if _serializer_class.is_a?(Proc) #TODO: maybe we should do duck typing instead?
297
- _serializer_class = self.collection_serializer_class
298
- end
264
+ def _relation_options
265
+ return @_relation_options if defined?(@_relation_options)
299
266
 
300
- if _serializer_class.respond_to?(:simple_ams?)
301
- return _serializer_class&.options
302
- else
303
- raise "#{_serializer_class} does not respond to SimpleAMS methods, did you include the DSL module?"
304
- end
305
- end
267
+ # TODO: should use 2.7 filter_map soon
268
+ @_relation_options = relations.each_with_object({}) do |relation, memo|
269
+ includes_value = (injected_options[:includes] || {}).find do |incl_hash|
270
+ next unless incl_hash.is_a?(Hash)
306
271
 
307
- def instantiated_serializer_for(serializer_klass)
308
- serializer_klass.new.extend(
309
- SimpleAMS::Methy.of(
310
- expose.merge({
311
- object: resource
312
- })
313
- )
314
- )
272
+ incl_hash.keys.include?(relation.name)
315
273
  end
274
+ includes_value = if includes_value
275
+ includes_value[relation.name]
276
+ else
277
+ # it's important here to return empty array if nothing is found..
278
+ []
279
+ end
316
280
 
317
- def infer_serializer
318
- namespace = _internal[:module] ? "#{_internal[:module]}::" : ""
319
- resource_klass = resource.kind_of?(Array) ? resource[0].class : resource.class
320
- if resource_klass == NilClass
321
- return EmptySerializer
322
- else
323
- return Object.const_get("#{namespace}#{resource_klass.to_s}Serializer")
324
- end
325
- rescue NameError => _
326
- raise "Could not infer serializer for #{resource.class}, maybe specify it? (tried #{namespace}#{resource_klass.to_s}Serializer)"
327
- end
281
+ fields_value = (injected_options[:fields] || {}).find do |field_hash|
282
+ next unless field_hash.is_a?(Hash)
328
283
 
329
- class EmptySerializer
330
- include SimpleAMS::DSL
284
+ field_hash.keys.include?(relation.name)
331
285
  end
286
+
287
+ # .. while here just nil will work (pick default fields from serializer)
288
+ fields_value = fields_value[relation.name] if fields_value
289
+
290
+ memo[relation.name] = {
291
+ includes: includes_value,
292
+ fields: fields_value
293
+ }
294
+ end
295
+ end
296
+
297
+ # TODO: raise exception if both are nil!
298
+ def fetch_allowed_options
299
+ _serializer_class = serializer_class
300
+ _serializer_class = collection_serializer_class if _serializer_class.is_a?(Proc)
301
+
302
+ unless _serializer_class.respond_to?(:simple_ams?)
303
+ raise "#{_serializer_class} does not respond to SimpleAMS methods, did you include the DSL module?"
304
+ end
305
+
306
+ _serializer_class&.options
307
+ end
308
+
309
+ def instantiated_serializer_for(serializer_klass)
310
+ serializer_klass.new.extend(
311
+ SimpleAMS::Methy.of(
312
+ expose.merge({
313
+ object: resource
314
+ })
315
+ )
316
+ )
317
+ end
318
+
319
+ def infer_serializer
320
+ namespace = _internal[:module] ? "#{_internal[:module]}::" : ''
321
+ resource_klass = resource.respond_to?(:to_a) && resource.respond_to?(:last) ? resource[0].class : resource.class
322
+ if resource_klass == NilClass
323
+ EmptySerializer
324
+ else
325
+ Object.const_get("#{namespace}#{resource_klass}Serializer")
326
+ end
327
+ rescue NameError => _e
328
+ tried = "#{namespace}#{resource_klass}Serializer"
329
+ raise "Could not infer serializer for #{resource.class}, maybe specify it? (tried #{tried})"
330
+ end
331
+
332
+ class EmptySerializer
333
+ include SimpleAMS::DSL
332
334
  end
333
335
  end