jsonapi-resources 0.9.5 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9d5578a1c15d0e7c0c5726406827aa473dd39349
4
- data.tar.gz: 6ded3ed7fc3b01a7811d8a58159cb54c27ec7e26
2
+ SHA256:
3
+ metadata.gz: aca973f2c9c1164fc79771cc71b363be15d07159cbe8d2b273d63886fee30b05
4
+ data.tar.gz: cdd800dde1c3f08d6b7c1d6f904f7519f0168c7585a4a9e6b8d4ecf89e834e1c
5
5
  SHA512:
6
- metadata.gz: 72967c7e6284bc8c0e667fae9899173dc985d4ebd7986a4aa891d4b17154b6c337bd7784acee269224aae5b5f97040d80a6e74db85fd2068155ce8fdadd5fc84
7
- data.tar.gz: 1146acf9b97328aef64efb8a6ed675b3a5e1378a08eeb18fc85f91f548dcf821ec939a9e70271ff3d2fd6ff8e0cfb30de60df2d08ba91ce59858361cdc4e3819
6
+ metadata.gz: 509137860c1e0a0a842a15ebeb580e229cc0636623ebc3d70aef2d752979bd066dc6ba2268bbdad483acdc1a5c25701c62eb9876b796effa80dd2e841fd4ef4d
7
+ data.tar.gz: b9dfc40e043337a749502f70f790e9280bf08e8a267bf0181e48522b27f58b8d1205cce28bc7e866adc6c566399cc313f3442a4aba86b1a6ef256e36b0f50873
@@ -197,7 +197,7 @@ module JSONAPI
197
197
  (paginator && paginator.class.requires_record_count) ||
198
198
  (JSONAPI.configuration.top_level_meta_include_page_count))
199
199
  related_resource_records = source_resource.public_send("records_for_" + relationship_type)
200
- records = resource_klass.filter_records(verified_filters, {},
200
+ records = resource_klass.filter_records(verified_filters, rel_opts,
201
201
  related_resource_records)
202
202
 
203
203
  record_count = resource_klass.count_records(records)
@@ -251,34 +251,41 @@ module JSONAPI
251
251
  end
252
252
 
253
253
  filters.each do |key, value|
254
- filter_method, included_resource_name =
255
- key.to_s.split('.').map { |k| unformat_key(k) }.reverse
256
254
 
257
- if included_resource_name
258
- relationship = resource_klass._relationship(included_resource_name || '')
255
+ unformatted_key = unformat_key(key)
256
+ if resource_klass._allowed_filter?(unformatted_key)
257
+ @filters[unformatted_key] = value
258
+ elsif unformatted_key.to_s.include?('.')
259
+ parse_relationship_filter(unformatted_key, value)
260
+ else
261
+ return @errors.concat(Exceptions::FilterNotAllowed.new(unformatted_key).errors)
262
+ end
263
+ end
264
+ end
259
265
 
260
- unless relationship
261
- return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
262
- end
266
+ def parse_relationship_filter(key, value)
267
+ included_resource_name, filter_method = key.to_s.split('.')
268
+ filter_method = filter_method.to_sym if filter_method.present?
263
269
 
264
- unless relationship.resource_klass._allowed_filter?(filter_method)
265
- return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
266
- end
270
+ if included_resource_name
271
+ relationship = resource_klass._relationship(included_resource_name || '')
267
272
 
268
- unless @include_directives.include_config(relationship.name.to_sym).present?
269
- return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
270
- end
273
+ unless relationship
274
+ return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
275
+ end
271
276
 
272
- verified_filter = relationship.resource_klass.verify_filters(filter_method => value)
273
- @include_directives.merge_filter(relationship.name, verified_filter)
274
- next
275
- else
276
- unless resource_klass._allowed_filter?(filter_method)
277
- return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
278
- end
277
+ unless relationship.resource_klass._allowed_filter?(filter_method)
278
+ return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
279
+ end
279
280
 
280
- @filters[filter_method] = value
281
+ unless @include_directives.try(:include_config, relationship.name.to_sym).present?
282
+ return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
281
283
  end
284
+
285
+ verified_filter = relationship.resource_klass.verify_filters(filter_method => value)
286
+ @include_directives.merge_filter(relationship.name, verified_filter)
287
+ else
288
+ return @errors.concat(Exceptions::FilterNotAllowed.new(filter_method).errors)
282
289
  end
283
290
  end
284
291
 
@@ -521,20 +528,40 @@ module JSONAPI
521
528
 
522
529
  links_object = parse_to_many_links_object(linkage)
523
530
 
524
- # Since we do not yet support polymorphic to_many relationships we will raise an error if the type does not match the
525
- # relationship's type.
526
- # ToDo: Support Polymorphic relationships
527
-
528
531
  if links_object.length == 0
529
532
  add_result.call([])
530
533
  else
531
- if links_object.length > 1 || !links_object.has_key?(unformat_key(relationship.type).to_s)
532
- fail JSONAPI::Exceptions::TypeMismatch.new(links_object[:type])
533
- end
534
+ if relationship.polymorphic?
535
+ polymorphic_results = []
536
+
537
+ links_object.each_pair do |type, keys|
538
+ resource = self.resource_klass || Resource
539
+ type_name = unformat_key(type).to_s
540
+
541
+ relationship_resource_klass = resource.resource_for(relationship.class_name)
542
+ relationship_klass = relationship_resource_klass._model_class
543
+
544
+ linkage_object_resource_klass = resource.resource_for(type_name)
545
+ linkage_object_klass = linkage_object_resource_klass._model_class
546
+
547
+ unless linkage_object_klass == relationship_klass || linkage_object_klass.in?(relationship_klass.subclasses)
548
+ fail JSONAPI::Exceptions::TypeMismatch.new(type_name)
549
+ end
550
+
551
+ relationship_ids = relationship_resource_klass.verify_keys(keys, @context)
552
+ polymorphic_results << { type: type, ids: relationship_ids }
553
+ end
554
+
555
+ add_result.call polymorphic_results
556
+ else
557
+ relationship_type = unformat_key(relationship.type).to_s
558
+
559
+ if links_object.length > 1 || !links_object.has_key?(relationship_type)
560
+ fail JSONAPI::Exceptions::TypeMismatch.new(links_object[:type])
561
+ end
534
562
 
535
- links_object.each_pair do |type, keys|
536
- relationship_resource = Resource.resource_for(@resource_klass.module_path + unformat_key(type).to_s)
537
- add_result.call relationship_resource.verify_keys(keys, @context)
563
+ relationship_resource = Resource.resource_for(@resource_klass.module_path + relationship_type)
564
+ add_result.call relationship_resource.verify_keys(links_object[relationship_type], @context)
538
565
  end
539
566
  end
540
567
  end
@@ -302,6 +302,26 @@ module JSONAPI
302
302
  to_add = relationship_key_values - (relationship_key_values & existing)
303
303
  _create_to_many_links(relationship_type, to_add, {})
304
304
 
305
+ @reload_needed = true
306
+ elsif relationship.polymorphic?
307
+ relationship_key_values.each do |relationship_key_value|
308
+ relationship_resource_klass = self.class.resource_for(relationship_key_value[:type])
309
+ ids = relationship_key_value[:ids]
310
+
311
+ related_records = relationship_resource_klass
312
+ .records(options)
313
+ .where({relationship_resource_klass._primary_key => ids})
314
+
315
+ missed_ids = ids - related_records.pluck(relationship_resource_klass._primary_key)
316
+
317
+ if missed_ids.present?
318
+ fail JSONAPI::Exceptions::RecordNotFound.new(missed_ids)
319
+ end
320
+
321
+ relation_name = relationship.relation_name(context: @context)
322
+ @model.send("#{relation_name}") << related_records
323
+ end
324
+
305
325
  @reload_needed = true
306
326
  else
307
327
  send("#{relationship.foreign_key}=", relationship_key_values)
@@ -565,7 +585,14 @@ module JSONAPI
565
585
  _add_relationship(Relationship::ToMany, *attrs)
566
586
  end
567
587
 
588
+ # @model_class is inherited from superclass, and this causes some issues:
589
+ # ```
590
+ # CarResource._model_class #=> Vehicle # it should be Car
591
+ # ```
592
+ # so in order to invoke the right class from subclasses,
593
+ # we should call this method to override it.
568
594
  def model_name(model, options = {})
595
+ @model_class = nil
569
596
  @_model_name = model.to_sym
570
597
 
571
598
  model_hint(model: @_model_name, resource: self) unless options[:add_model_hint] == false
@@ -394,12 +394,16 @@ module JSONAPI
394
394
 
395
395
  def to_many_linkage(source, relationship)
396
396
  linkage = []
397
+ include_config = include_directives.include_config(relationship.name.to_sym) if include_directives
398
+ include_filters = include_config[:include_filters] if include_config
399
+ options = { filters: include_filters || {} }
400
+
397
401
  linkage_types_and_values = if source.preloaded_fragments.has_key?(format_key(relationship.name))
398
402
  source.preloaded_fragments[format_key(relationship.name)].map do |_, resource|
399
403
  [relationship.type, resource.id]
400
404
  end
401
405
  elsif relationship.polymorphic?
402
- assoc = source._model.public_send(relationship.name)
406
+ assoc = source.public_send("records_for_#{relationship.name}", options)
403
407
  # Avoid hitting the database again for values already pre-loaded
404
408
  if assoc.respond_to?(:loaded?) and assoc.loaded?
405
409
  assoc.map do |obj|
@@ -411,9 +415,6 @@ module JSONAPI
411
415
  end
412
416
  end
413
417
  else
414
- include_config = include_directives.include_config(relationship.name.to_sym) if include_directives
415
- include_filters = include_config[:include_filters] if include_config
416
- options = { filters: include_filters || {} }
417
418
  source.public_send(relationship.name, options).map do |value|
418
419
  [relationship.type, value.id]
419
420
  end
@@ -1,5 +1,5 @@
1
1
  module JSONAPI
2
2
  module Resources
3
- VERSION = '0.9.5'
3
+ VERSION = '0.9.6'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 0.9.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Gebhardt
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-01-09 00:00:00.000000000 Z
12
+ date: 2019-03-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -109,6 +109,20 @@ dependencies:
109
109
  - - ">="
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: database_cleaner
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
112
126
  - !ruby/object:Gem::Dependency
113
127
  name: activerecord
114
128
  requirement: !ruby/object:Gem::Requirement
@@ -217,7 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
231
  version: '0'
218
232
  requirements: []
219
233
  rubyforge_project:
220
- rubygems_version: 2.6.14.1
234
+ rubygems_version: 2.7.6
221
235
  signing_key:
222
236
  specification_version: 4
223
237
  summary: Easily support JSON API in Rails.