Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions lib/jsonapi/renderer/resources_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,42 @@ def traverse_resource(res, include_keys, primary)

if @include_rels.include?(ri)
@include_rels[ri].merge!(keys_hash)

include_duplicate_resource(res) unless primary
else
@include_rels[ri] = keys_hash
(primary ? @primary : @included) << res
end
end

def include_duplicate_resource(res)
duplicate_index = find_included_duplicate_resource(res)

return unless duplicate_index

duplicate = @included.delete_at(duplicate_index)

if duplicate.is_a?(Array)
duplicate << res
else
duplicate = [duplicate, res]
end

@included << duplicate
end

def find_included_duplicate_resource(res)
@included.find_index do |included|
if included.is_a?(Array)
unless included.empty?
included.first.jsonapi_type == res.jsonapi_type && included.first.jsonapi_id == res.jsonapi_id
end
else
included.jsonapi_type == res.jsonapi_type && included.jsonapi_id == res.jsonapi_id
end
end
end

def enqueue_related_resources(res, prefix, include_dir)
res.jsonapi_related(include_dir.keys).each do |key, data|
child_prefix = "#{prefix}.#{key}".freeze
Expand Down
47 changes: 43 additions & 4 deletions lib/jsonapi/renderer/simple_resources_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,52 @@ class SimpleResourcesProcessor < ResourcesProcessor
def process_resources
[@primary, @included].each do |resources|
resources.map! do |res|
ri = [res.jsonapi_type, res.jsonapi_id]
include_dir = @include_rels[ri].keys
fields = @fields[res.jsonapi_type.to_sym]
res.as_jsonapi(include: include_dir, fields: fields)
# Duplicates array
if res.is_a?(Array)
process_duplicates(res)
# Regular resource case
else
process_resource(res)
end
end
end
end

def process_resource(resource)
ri = [resource.jsonapi_type, resource.jsonapi_id]
include_dir = @include_rels[ri].keys
fields = @fields[resource.jsonapi_type.to_sym]
resource.as_jsonapi(include: include_dir, fields: fields)
end

def process_duplicates(duplicates)
return unless duplicates.is_a?(Array) && duplicates.any?

duplicates.inject({}) do |result, duplicate|
if result.empty?
result = process_resource(duplicate) if result.empty?
else
duplicate_result = process_resource(duplicate)
result = deep_merge_duplicate_hashes(result, duplicate_result)
end
end
end

def deep_merge_duplicate_hashes(hash1, hash2)
merger = proc do |_, v1, v2|
if v1.is_a?(Hash) && v2.is_a?(Hash)
v1.merge(v2, &merger)
elsif v1.is_a?(Array) && v2.is_a?(Array)
v1 | v2
elsif [:undefined, nil, :nil].include?(v2)
v1
else
v2
end
end

hash1.merge(hash2, &merger)
end
end
end
end