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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
require 'jsonapi/include_directive'
require 'jsonapi/renderer/simple_resources_processor'
require 'jsonapi/renderer/cached_resources_processor'
module JSONAPI
class Renderer
# @private
class Document
def initialize(params = {})
@data = params.fetch(:data, :no_data)
@errors = params.fetch(:errors, [])
@meta = params[:meta]
@links = params[:links] || {}
@fields = _canonize_fields(params[:fields] || {})
@jsonapi = params[:jsonapi]
@include = JSONAPI::IncludeDirective.new(params[:include] || {})
@relationship = params[:relationship]
@cache = params[:cache]
end
def to_hash
@hash ||= document_hash
end
alias to_h to_hash
private
# rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength
# rubocop:disable Metrics/CyclomaticComplexity
def document_hash
{}.tap do |hash|
if @relationship
hash.merge!(relationship_hash)
elsif @data != :no_data
hash.merge!(data_hash)
elsif @errors.any?
hash.merge!(errors_hash)
end
hash[:links] = @links if @links.any?
hash[:meta] = @meta unless @meta.nil?
hash[:jsonapi] = @jsonapi unless @jsonapi.nil?
end
end
# rubocop:enable Metrics/PerceivedComplexity, Metrics/MethodLength
# rubocop:enable Metrics/CyclomaticComplexity
def data_hash
primary, included =
resources_processor.process(Array(@data), @include, @fields)
{}.tap do |hash|
hash[:data] = @data.respond_to?(:to_ary) ? primary : primary[0]
hash[:included] = included if included.any?
end
end
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
def relationship_hash
rel_name = @relationship.to_sym
data = @data.jsonapi_related([rel_name])[rel_name]
included =
if @include.key?(rel_name)
resources_processor.process(data, @include[rel_name], @fields)
.flatten!
else
[]
end
res = @data.as_jsonapi(fields: [rel_name], include: [rel_name])
rel = res[:relationships][rel_name]
@links = rel[:links].merge!(@links)
@meta ||= rel[:meta]
{}.tap do |hash|
hash[:data] = rel[:data]
hash[:included] = included if included.any?
end
end
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
def errors_hash
{}.tap do |hash|
hash[:errors] = @errors.flat_map(&:as_jsonapi)
end
end
def resources_processor
if @cache
CachedResourcesProcessor.new(@cache)
else
SimpleResourcesProcessor.new
end
end
def _canonize_fields(fields)
fields.each_with_object({}) do |(k, v), h|
h[k.to_sym] = v.map(&:to_sym).sort!
end
end
end
end
end
|