1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
require 'set'
module JSONAPI
class Renderer
# @private
class ResourcesProcessor
def process(resources, include, fields)
@resources = resources
@include = include
@fields = fields
traverse_resources
process_resources
[@primary, @included]
end
private
def traverse_resources
@traversed = Set.new # [type, id, prefix]
@include_rels = {} # [type, id => Set]
@queue = []
@primary = []
@included = []
initialize_queue
traverse_queue
end
def initialize_queue
@resources.each do |res|
@traversed.add([res.jsonapi_type, res.jsonapi_id, ''])
traverse_resource(res, @include.keys, true)
enqueue_related_resources(res, '', @include)
end
end
def traverse_queue
until @queue.empty?
res, prefix, include_dir = @queue.shift
traverse_resource(res, include_dir.keys, false)
enqueue_related_resources(res, prefix, include_dir)
end
end
def traverse_resource(res, include_keys, primary)
ri = [res.jsonapi_type, res.jsonapi_id]
if @include_rels.include?(ri)
@include_rels[ri].merge(include_keys)
else
@include_rels[ri] = Set.new(include_keys)
(primary ? @primary : @included) << res
end
end
def enqueue_related_resources(res, prefix, include_dir)
res.jsonapi_related(include_dir.keys).each do |key, data|
data.each do |child_res|
next if child_res.nil?
child_prefix = "#{prefix}.#{key}"
enqueue_resource(child_res, child_prefix, include_dir[key])
end
end
end
def enqueue_resource(res, prefix, include_dir)
return unless @traversed.add?([res.jsonapi_type,
res.jsonapi_id,
prefix])
@queue << [res, prefix, include_dir]
end
def process_resources
raise 'Not implemented'
end
end
end
end
|