module JSONAPI::Deserialization

Helpers to transform a JSON API document, containing a single data object, into a hash that can be used to create an [ActiveRecord::Base] instance.

Initial version from the `active_model_serializers` support for JSONAPI.

Private Instance Methods

jsonapi_deserialize(document, options = {}) click to toggle source

Returns a transformed dictionary following [ActiveRecord::Base] specs

@param [Hash|ActionController::Parameters] document @param [Hash] options

only: Array of symbols of whitelisted fields.
except: Array of symbols of blacklisted fields.
polymorphic: Array of symbols of polymorphic fields.

@return [Hash]

# File lib/jsonapi/deserialization.rb, line 35
def jsonapi_deserialize(document, options = {})
  if document.respond_to?(:permit!)
    # Handle Rails params...
    primary_data = document.dup.require(:data).permit!.as_json
  elsif document.is_a?(Hash)
    primary_data = (document.as_json['data'] || {}).deep_dup
  else
    return {}
  end

  # Transform keys and any option values.
  options = options.as_json
  ['only', 'except', 'polymorphic'].each do |opt_name|
    opt_value = options[opt_name]
    options[opt_name] = Array(opt_value).map(&:to_s) if opt_value
  end

  relationships = primary_data['relationships'] || {}
  parsed = primary_data['attributes'] || {}
  parsed['id'] = primary_data['id'] if primary_data['id']

  # Remove unwanted items from a dictionary.
  if options['only']
    [parsed, relationships].map { |hsh| hsh.slice!(*options['only']) }
  elsif options['except']
    [parsed, relationships].map { |hsh| hsh.except!(*options['except']) }
  end

  relationships.map do |assoc_name, assoc_data|
    assoc_data = (assoc_data || {})['data'] || {}
    rel_name = jsonapi_inflector.singularize(assoc_name)

    if assoc_data.is_a?(Array)
      parsed["#{rel_name}_ids"] = assoc_data.map { |ri| ri['id'] }.compact
      next
    end

    parsed["#{rel_name}_id"] = assoc_data['id']

    if (options['polymorphic'] || []).include?(assoc_name)
      rel_type = jsonapi_inflector.classify(assoc_data['type'].to_s)
      parsed["#{rel_name}_type"] = rel_type
    end
  end

  parsed
end
jsonapi_inflector() click to toggle source

Helper method to pick an available inflector implementation

@return [Object]

# File lib/jsonapi/deserialization.rb, line 21
def jsonapi_inflector
  ActiveSupport::Inflector
rescue
  Dry::Inflector.new
end