class ActiveModelSerializers::Adapter::JsonApi

def self.default_key_transform

def self.default_key_transform
  :dash
end

def self.fragment_cache(cached_hash, non_cached_hash, root = true)

def self.fragment_cache(cached_hash, non_cached_hash, root = true)
  core_cached       = cached_hash.first
  core_non_cached   = non_cached_hash.first
  no_root_cache     = cached_hash.delete_if { |key, _value| key == core_cached[0] }
  no_root_non_cache = non_cached_hash.delete_if { |key, _value| key == core_non_cached[0] }
  cached_resource   = (core_cached[1]) ? core_cached[1].deep_merge(core_non_cached[1]) : core_non_cached[1]
  hash = root ? { root => cached_resource } : cached_resource
  hash.deep_merge no_root_non_cache.deep_merge no_root_cache
end

def attributes_for(serializer, fields)

}
foo: 'bar'
{
structure:
Attributes may contain any valid JSON value
object in which it's defined.
Members of the attributes object ("attributes") represent information about the resource
description:

^(?!relationships$|links$)\\w[-\\w_]*$
patternProperties:

JSON Object
definition:
attributes
{http://jsonapi.org/format/#document-resource-object-attributes Document Resource Object Attributes}
def attributes_for(serializer, fields)
  serializer.attributes(fields).except(:id)
end

def failure_document

https://github.com/rails-api/active_model_serializers/pull/1004
prs:
}.reject! {|_,v| v.nil? }
jsonapi: toplevel_jsonapi
meta: toplevel_meta,
errors: toplevel_errors,
{
structure:
☐ toplevel_jsonapi
☐ toplevel_meta
☑ toplevel_errors array (required)
definition:
TODO: look into caching
{http://jsonapi.org/format/#errors JSON API Errors}
def failure_document
  hash = {}
  # PR Please :)
  # Jsonapi.add!(hash)
  # toplevel_errors
  # definition:
  #   array of unique items of type 'error'
  # structure:
  #   [
  #     error,
  #     error
  #   ]
  if serializer.respond_to?(:each)
    hash[:errors] = serializer.flat_map do |error_serializer|
      Error.resource_errors(error_serializer, instance_options)
    end
  else
    hash[:errors] = Error.resource_errors(serializer, instance_options)
  end
  hash
end

def fragment_cache(cached_hash, non_cached_hash)

def fragment_cache(cached_hash, non_cached_hash)
  root = !instance_options.include?(:include)
  self.class.fragment_cache(cached_hash, non_cached_hash, root)
end

def initialize(serializer, options = {})

def initialize(serializer, options = {})
  super
  @include_directive = JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
  @fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields))
end

def links_for(serializer)

}.reject! {|_,v| v.nil? }
related: link
self: 'http://example.com/etc',
{
structure:
itself.
a client to remove an `author` from an `article` without deleting the people resource
URL allows the client to directly manipulate the relationship. For example, it would allow
A `self` member’s value is a URL for the relationship itself (a "relationship URL"). This

in a resource's links object.
Relationships may be to-one or to-many. Relationships can be specified by including a member
A resource object **MAY** contain references to other resource objects ("relationships").
description:

related : link
self : URI
properties:

JSON Object
definition:
links
{http://jsonapi.org/format/#document-links Document Links}
def links_for(serializer)
  serializer._links.each_with_object({}) do |(name, value), hash|
    result = Link.new(serializer, value).as_json
    hash[name] = result if result
  end
end

def meta_for(serializer)

{http://jsonapi.org/format/#document-meta Docment Meta}
def meta_for(serializer)
  Meta.new(serializer).as_json
end

def pagination_links_for(serializer)

https://github.com/rails-api/active_model_serializers/pull/1041
prs:
end
nil
else
'http://example.com/some-page?page[number][x]'
if has_page?
structure:
The page of data
description:

null
URI
oneOf
definition:
pageObject

}
next: pageObject
prev: pageObject,
last: pageObject,
first: pageObject,
{
structure:
next : pageObject
prev : pageObject
last : pageObject
first : pageObject
definition:
pagination
{http://jsonapi.org/format/#fetching-pagination Pagination Links}
def pagination_links_for(serializer)
  PaginationLinks.new(serializer.object, instance_options).as_json
end

def process_relationship(serializer, include_directive)

def process_relationship(serializer, include_directive)
  if serializer.respond_to?(:each)
    serializer.each { |s| process_relationship(s, include_directive) }
    return
  end
  return unless serializer && serializer.object
  return unless process_resource(serializer, false)
  process_relationships(serializer, include_directive)
end

def process_relationships(serializer, include_directive)

def process_relationships(serializer, include_directive)
  serializer.associations(include_directive).each do |association|
    process_relationship(association.serializer, include_directive[association.key])
  end
end

def process_resource(serializer, primary)

def process_resource(serializer, primary)
  resource_identifier = ResourceIdentifier.new(serializer, instance_options).as_json
  return false unless @resource_identifiers.add?(resource_identifier)
  resource_object = resource_object_for(serializer)
  if primary
    @primary << resource_object
  else
    @included << resource_object
  end
  true
end

def relationships_for(serializer, requested_associations)

}.reject! {|_,v| v.nil? }
meta: meta
id: 'required-id',
type: 'required-type',
{
structure:
The "type" and "id" to non-empty members.
description:

meta
id (required) : String
type (required) : String
definition:
linkage

[ ] https://github.com/rails-api/active_model_serializers/pull/1282
polymorphic
prs:
]
linkage
linkage,
[
structure:
An array of objects each containing "type" and "id" members for to-many relationships
description:

array of unique items of type 'linkage'
definition:
relationshipToMany

end
nil
else
linkage
if has_related?
structure:
None: Describes an empty to-one relationship.

specified by including a member in a resource's links object.
References to other resource objects in a to-one ("relationship"). Relationships can be

description:
relationshipToOne

linkage
null
anyOf
definition:

end
relationshipToMany
else
relationshipToOne
if has_one?
structure:
Member, whose value represents "resource linkage"
description:

relationshipToMany
relationshipToOne
oneOf
definition:
relationshipsData

[ ] https://github.com/rails-api/active_model_serializers/pull/1420
polymorphic
[x] https://github.com/rails-api/active_model_serializers/pull/1454
meta
[x] https://github.com/rails-api/active_model_serializers/pull/1454
links
prs:

}.reject! {|_,v| v.nil? }
data: relationshipsData
meta: meta,
links: links,
{
structure:
resource object in which it's defined to other resource objects."
Members of the relationships object ("relationships") represent references from the

description:

meta
links
data : relationshipsData
properties:

^\\w[-\\w_]*$"
patternProperties:

JSON Object
definition:
relationships
{http://jsonapi.org/format/#document-resource-object-relationships Document Resource Object Relationship}
def relationships_for(serializer, requested_associations)
  include_directive = JSONAPI::IncludeDirective.new(
    requested_associations,
    allow_wildcard: true
  )
  serializer.associations(include_directive).each_with_object({}) do |association, hash|
    hash[association.key] = Relationship.new(
      serializer,
      association.serializer,
      instance_options,
      options: association.options,
      links: association.links,
      meta: association.meta
    ).as_json
  end
end

def resource_object_for(serializer)

{http://jsonapi.org/format/#document-resource-objects Document Resource Objects}
def resource_object_for(serializer)
  resource_object = serializer.fetch(self) do
    resource_object = ResourceIdentifier.new(serializer, instance_options).as_json
    requested_fields = fieldset && fieldset.fields_for(resource_object[:type])
    attributes = attributes_for(serializer, requested_fields)
    resource_object[:attributes] = attributes if attributes.any?
    resource_object
  end
  requested_associations = fieldset.fields_for(resource_object[:type]) || '*'
  relationships = relationships_for(serializer, requested_associations)
  resource_object[:relationships] = relationships if relationships.any?
  links = links_for(serializer)
  # toplevel_links
  # definition:
  #   allOf
  #      ☐ links
  #      ☐ pagination
  #
  # description:
  #  Link members related to the primary data.
  # structure:
  #   links.merge!(pagination)
  # prs:
  #   https://github.com/rails-api/active_model_serializers/pull/1247
  #   https://github.com/rails-api/active_model_serializers/pull/1018
  resource_object[:links] = links if links.any?
  # toplevel_meta
  #   alias meta
  # definition:
  #   meta
  # structure
  #   {
  #     :'git-ref' => 'abc123'
  #   }
  meta = meta_for(serializer)
  resource_object[:meta] = meta unless meta.blank?
  resource_object
end

def resource_objects_for(serializers)

[x] https://github.com/rails-api/active_model_serializers/pull/1340
meta
[x] url helpers https://github.com/rails-api/active_model_serializers/issues/1269
[x] https://github.com/rails-api/active_model_serializers/pull/1246
links
https://github.com/rails-api/active_model_serializers/pull/1029
https://github.com/rails-api/active_model_serializers/pull/1216
[x] https://github.com/rails-api/active_model_serializers/pull/1213
https://github.com/rails-api/active_model_serializers/pull/1122
type
prs:
}.reject! {|_,v| v.nil? }
meta: meta,
links: links,
relationships: relationships,
attributes: attributes,
id: '1336',
type: 'admin--some-user',
{
structure:
"Resource objects" appear in a JSON API document to represent resources
description:

meta
links
relationships
attributes
id (required) : String
type (required) : String
properties:

JSON Object
definition:
resource
{http://jsonapi.org/format/#document-resource-objects Primary data}
def resource_objects_for(serializers)
  @primary = []
  @included = []
  @resource_identifiers = Set.new
  serializers.each { |serializer| process_resource(serializer, true) }
  serializers.each { |serializer| process_relationships(serializer, @include_directive) }
  [@primary, @included]
end

def serializable_hash(*)

{http://jsonapi.org/format/#document-top-level data and errors MUST NOT coexist in the same document.}
{http://jsonapi.org/format/#crud Requests are transactional, i.e. success or failure}
def serializable_hash(*)
  document = if serializer.success?
               success_document
             else
               failure_document
             end
  self.class.transform_key_casing!(document, instance_options)
end

def success_document

rubocop:disable Metrics/CyclomaticComplexity
}.reject! {|_,v| v.nil? }
jsonapi: toplevel_jsonapi
links: toplevel_links,
meta: toplevel_meta,
included: toplevel_included,
data: toplevel_data,
{
structure:
☑ toplevel_jsonapi
☑ toplevel_links
☑ toplevel_meta
☐ toplevel_included
☐ toplevel_data (required)
definition:
{http://jsonapi.org/format/#document-top-level Primary data}
def success_document
  is_collection = serializer.respond_to?(:each)
  serializers = is_collection ? serializer : [serializer]
  primary_data, included = resource_objects_for(serializers)
  hash = {}
  # toplevel_data
  # definition:
  #   oneOf
  #     resource
  #     array of unique items of type 'resource'
  #     null
  #
  # description:
  #   The document's "primary data" is a representation of the resource or collection of resources
  #   targeted by a request.
  #
  #   Singular: the resource object.
  #
  #   Collection: one of an array of resource objects, an array of resource identifier objects, or
  #   an empty array ([]), for requests that target resource collections.
  #
  #   None: null if the request is one that might correspond to a single resource, but doesn't currently.
  # structure:
  #  if serializable_resource.resource?
  #    resource
  #  elsif serializable_resource.collection?
  #    [
  #      resource,
  #      resource
  #    ]
  #  else
  #    nil
  #  end
  hash[:data] = is_collection ? primary_data : primary_data[0]
  # toplevel_included
  #   alias included
  # definition:
  #   array of unique items of type 'resource'
  #
  # description:
  #   To reduce the number of HTTP requests, servers **MAY** allow
  #   responses that include related resources along with the requested primary
  #   resources. Such responses are called "compound documents".
  # structure:
  #     [
  #       resource,
  #       resource
  #     ]
  hash[:included] = included if included.any?
  Jsonapi.add!(hash)
  if instance_options[:links]
    hash[:links] ||= {}
    hash[:links].update(instance_options[:links])
  end
  if is_collection && serializer.paginated?
    hash[:links] ||= {}
    hash[:links].update(pagination_links_for(serializer))
  end
  hash[:meta] = instance_options[:meta] unless instance_options[:meta].blank?
  hash
end