module JsonApi::Parameters

Constants

LIMIT
VERSION

Attributes

ensure_underscore_translation[RW]

Public Instance Methods

jsonapify(params, naming_convention: :snake, custom_stack_limit: stack_limit) click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 6
def jsonapify(params, naming_convention: :snake, custom_stack_limit: stack_limit)
  initialize_stack(custom_stack_limit)

  jsonapi_translate(params, naming_convention: naming_convention)
end
reset_stack_limit() click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 16
def reset_stack_limit
  @stack_limit = LIMIT
end
stack_limit() click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 12
def stack_limit
  @stack_limit || LIMIT
end
stack_limit=(val) click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 8
def stack_limit=(val)
  @stack_limit = val
end

Private Instance Methods

decrement_stack_level() click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 33
def decrement_stack_level
  @current_stack_level -= 1
end
formed_parameters() click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 30
def formed_parameters
  @formed_parameters ||= {}.tap do |param|
    param[jsonapi_main_key.to_sym] = jsonapi_main_body
  end
end
handle_nested_relationships(val) click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 95
def handle_nested_relationships(val)
  # We can only consider Hash relationships (which imply to-one relationship) and Array relationships (which imply to-many).
  # Each type has a different handling method, though in both cases we end up passing the nested relationship recursively to handle_relationship
  # (and yes, this may go on indefinitely, basically we're going by the relationship levels, deeper and deeper)
  case val
  when Array
    relationships_with_nested_relationships = val.select { |rel| rel.is_a?(Hash) && rel.dig(:relationships) }
    relationships_with_nested_relationships.each do |relationship_with_nested_relationship|
      relationship_with_nested_relationship.delete(:relationships).each do |rel_key, rel_val|
        relationship_with_nested_relationship = handle_relationships(relationship_with_nested_relationship, rel_key, rel_val)
      end
    end
  when Hash
    if val.key?(:relationships)
      val.delete(:relationships).each do |rel_key, rel_val|
        val = handle_relationships(val, rel_key, rel_val)
      end
    end
  end

  val
end
handle_relationships(param, relationship_key, relationship_value) click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 66
def handle_relationships(param, relationship_key, relationship_value)
  increment_stack_level!

  relationship_value = relationship_value[:data]
  handler_args = [relationship_key, relationship_value, jsonapi_included]
  handler = if Handlers.resource_handlers.key?(relationship_key)
              Handlers.handlers[Handlers.resource_handlers[relationship_key]]
            else
              case relationship_value
              when Array
                Handlers.handlers[:to_many]
              when Hash
                Handlers.handlers[:to_one]
              when nil
                Handlers.handlers[:nil]
              else
                raise NotImplementedError.new('relationship resource linkage has to be a type of Array, Hash or nil')
              end
            end

  key, val = handler.call(*handler_args)

  param[key] = handle_nested_relationships(val)

  param
ensure
  decrement_stack_level
end
increment_stack_level!() click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 27
def increment_stack_level!
  @current_stack_level += 1

  raise StackLevelTooDeepError.new(stack_exception_message) if @current_stack_level > stack_limit
end
initialize_stack(custom_stack_limit) click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 22
def initialize_stack(custom_stack_limit)
  @current_stack_level = 0
  @stack_limit = custom_stack_limit
end
jsonapi_included() click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 62
def jsonapi_included
  @jsonapi_included ||= @jsonapi_unsafe_hash[:included] || []
end
jsonapi_main_body() click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 40
def jsonapi_main_body
  jsonapi_unsafe_params.tap do |param|
    jsonapi_relationships.each do |relationship_key, relationship_value|
      param = handle_relationships(param, relationship_key, relationship_value)
    end
  end
ensure
  reset_stack_level
end
jsonapi_main_key() click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 36
def jsonapi_main_key
  @jsonapi_unsafe_hash.dig(:data, :type)&.singularize || ''
end
jsonapi_relationships() click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 58
def jsonapi_relationships
  @jsonapi_relationships ||= @jsonapi_unsafe_hash.dig(:data, :relationships) || []
end
jsonapi_translate(params, naming_convention:) click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 14
def jsonapi_translate(params, naming_convention:)
  params = params.to_unsafe_h if params.is_a?(ActionController::Parameters)

  return params if params.nil? || params.empty?

  @jsonapi_unsafe_hash = if naming_convention != :snake || JsonApi::Parameters.ensure_underscore_translation
                           params = params.deep_transform_keys { |key| key.to_s.underscore.to_sym }
                           params[:data][:type] = params[:data][:type].underscore if params.dig(:data, :type)
                           params
                         else
                           params.deep_symbolize_keys
                         end

  formed_parameters
end
jsonapi_unsafe_params() click to toggle source
# File lib/jsonapi_parameters/translator.rb, line 50
def jsonapi_unsafe_params
  @jsonapi_unsafe_params ||= (@jsonapi_unsafe_hash.dig(:data, :attributes) || {}).tap do |param|
    id = @jsonapi_unsafe_hash.dig(:data, :id)

    param[:id] = id if id.present?
  end
end
reset_stack_level() click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 37
def reset_stack_level
  @current_stack_level = 0
end
stack_exception_message() click to toggle source
# File lib/jsonapi_parameters/stack_limit.rb, line 41
def stack_exception_message
  "Stack level of nested payload is too deep: #{@current_stack_level}/#{stack_limit}. Please see the documentation on how to overwrite the limit."
end