module ActiveModelSerializers::Adapter::JsonApi::Deserialization

def field_key(field, options)

Other tags:
    Api: - private
def field_key(field, options)
  (options[:keys] || {}).fetch(field.to_sym, field).to_sym
end

def filter_fields(fields, options)

Other tags:
    Api: - private
def filter_fields(fields, options)
  if (only = options[:only])
    fields.slice!(*Array(only).map(&:to_s))
  elsif (except = options[:except])
    fields.except!(*Array(except).map(&:to_s))
  end
end

def parse(document, options = {})

on invalid payloads.
Same as parse!, but returns an empty hash instead of raising InvalidDocument
def parse(document, options = {})
  document = document.dup.permit!.to_h if document.is_a?(ActionController::Parameters)
  validate_payload(document) do |invalid_document, reason|
    yield invalid_document, reason if block_given?
    return {}
  end
  primary_data = document['data']
  attributes = primary_data['attributes'] || {}
  attributes['id'] = primary_data['id'] if primary_data['id']
  relationships = primary_data['relationships'] || {}
  filter_fields(attributes, options)
  filter_fields(relationships, options)
  hash = {}
  hash.merge!(parse_attributes(attributes, options))
  hash.merge!(parse_relationships(relationships, options))
  hash
end

def parse!(document, options = {})

Returns:
  • (Hash) -

Parameters:
  • options (Hash) --
  • document (Hash|ActionController::Parameters) --
def parse!(document, options = {})
  parse(document, options) do |invalid_payload, reason|
    fail InvalidDocument, "Invalid payload (#{reason}): #{invalid_payload}"
  end
end

def parse_attributes(attributes, options)

Other tags:
    Api: - private
def parse_attributes(attributes, options)
  transform_keys(attributes, options)
    .map { |(k, v)| { field_key(k, options) => v } }
    .reduce({}, :merge)
end

def parse_relationship(assoc_name, assoc_data, options)

Other tags:
    Api: - private

Returns:
  • (Hash{Symbol, Object}) -

Parameters:
  • options (Hash) --
  • assoc_data (Hash) --
  • assoc_name (Symbol) --
def parse_relationship(assoc_name, assoc_data, options)
  prefix_key = field_key(assoc_name, options).to_s.singularize
  hash =
    if assoc_data.is_a?(Array)
      { "#{prefix_key}_ids".to_sym => assoc_data.map { |ri| ri['id'] } }
    else
      { "#{prefix_key}_id".to_sym => assoc_data ? assoc_data['id'] : nil }
    end
  polymorphic = (options[:polymorphic] || []).include?(assoc_name.to_sym)
  if polymorphic
    hash["#{prefix_key}_type".to_sym] = assoc_data.present? ? assoc_data['type'].classify : nil
  end
  hash
end

def parse_relationships(relationships, options)

Other tags:
    Api: - private
def parse_relationships(relationships, options)
  transform_keys(relationships, options)
    .map { |(k, v)| parse_relationship(k, v['data'], options) }
    .reduce({}, :merge)
end

def transform_keys(hash, options)

Other tags:
    Api: - private
def transform_keys(hash, options)
  transform = options[:key_transform] || :underscore
  CaseTransform.send(transform, hash)
end

def validate_payload(payload)

Other tags:
    Api: - private
def validate_payload(payload)
  unless payload.is_a?(Hash)
    yield payload, 'Expected hash'
    return
  end
  primary_data = payload['data']
  unless primary_data.is_a?(Hash)
    yield payload, { data: 'Expected hash' }
    return
  end
  attributes = primary_data['attributes'] || {}
  unless attributes.is_a?(Hash)
    yield payload, { data: { attributes: 'Expected hash or nil' } }
    return
  end
  relationships = primary_data['relationships'] || {}
  unless relationships.is_a?(Hash)
    yield payload, { data: { relationships: 'Expected hash or nil' } }
    return
  end
  relationships.each do |(key, value)|
    unless value.is_a?(Hash) && value.key?('data')
      yield payload, { data: { relationships: { key => 'Expected hash with :data key' } } }
    end
  end
end