module Surrealist::ValueAssigner

A class that determines the correct value to return for serialization. May descend recursively.

Public Class Methods

assign(schema, instance) { |assign_nested_record(instance, value)| ... } click to toggle source

Assigns value returned from a method to a corresponding key in the schema hash.

@param [Object] instance the instance of the object which methods from the schema are called on. @param [Struct] schema containing a single schema key and value

@return [Hash] schema

# File lib/surrealist/value_assigner.rb, line 13
def assign(schema, instance)
  value = raw_value(instance, schema)

  # set to track and prevent infinite self references in surrealization
  @skip_set ||= Set.new

  if value.respond_to?(:build_schema)
    yield assign_nested_record(instance, value)
  elsif Helper.collection?(value) && !value.empty? && value.all? { |v| Helper.surrealist?(v.class) }
    yield assign_nested_collection(instance, value)
  else
    yield value
  end
end

Private Class Methods

assign_nested_collection(instance, value) click to toggle source

Assists in recursively generating schema for records while preventing infinite self-referencing

@param [Object] instance the instance of the object which methods from the schema are called on. @param [Object] value a value that has to be type-checked.

@return [Array] of schemas

# File lib/surrealist/value_assigner.rb, line 78
def assign_nested_collection(instance, value)
  return if @skip_set.include?(value.first.class)

  with_skip_set(instance.class) { Surrealist.surrealize_collection(value, raw: true) }
end
assign_nested_record(instance, value) click to toggle source

Assists in recursively generating schema for a record while preventing infinite self-referencing

@param [Object] instance the instance of the object which methods from the schema are called on. @param [Object] value a value that has to be type-checked.

@return [Hash] schema

# File lib/surrealist/value_assigner.rb, line 90
def assign_nested_record(instance, value)
  return if @skip_set.include?(value.class)

  with_skip_set(instance.class) { value.build_schema }
end
coerce_value(value, schema) click to toggle source

Coerces value if type check is passed

@param [Object] value the value to be checked and coerced @param [Struct] schema containing a single schema key and value

@raise Surrealist::InvalidTypeError if type-check failed at some point.

@return [Object] value to be further processed

# File lib/surrealist/value_assigner.rb, line 64
def coerce_value(value, schema)
  unless TypeHelper.valid_type?(value, schema.value)
    raise Surrealist::InvalidTypeError,
          "Wrong type for key `#{schema.key}`. Expected #{schema.value}, got #{value.class}."
  end
  TypeHelper.coerce(value, schema.value)
end
invoke_method(instance, method) click to toggle source

Checks if there is a custom serializer defined for the object and invokes the method

on it first only if the serializer has not defined the same method.

@param [Object] instance an instance of a model or a serializer @param [Symbol] method the schema key that represents the method to be invoked

@return [Object] the return value of the method

# File lib/surrealist/value_assigner.rb, line 48
def invoke_method(instance, method)
  object = instance.instance_variable_get(:@object)
  instance_method = instance.class.method_defined?(method) ||
                    instance.class.private_method_defined?(method)
  invoke_object = !instance_method && object && object.respond_to?(method, true)
  invoke_object ? object.send(method) : instance.send(method)
end
raw_value(instance, schema) click to toggle source

Generates first pass of serializing value, doing type check and coercion

@param [Object] instance the instance of the object which methods from the schema are called on. @param [Struct] schema containing a single schema key and value

@return [Object] value to be further processed

# File lib/surrealist/value_assigner.rb, line 36
def raw_value(instance, schema)
  value = instance.is_a?(Hash) ? instance[schema.key] : invoke_method(instance, schema.key)
  coerce_value(value, schema)
end
with_skip_set(klass) { || ... } click to toggle source

Run block with klass in skip set

@param [Class] klass of current instance.

@return [Object] block result

# File lib/surrealist/value_assigner.rb, line 101
def with_skip_set(klass)
  return yield if @skip_set.include?(klass)

  @skip_set.add(klass)
  result = yield
  @skip_set.delete(klass)
  result
end