module JSONAPI::Relationships::Serialization

def fetch_blank_polymorphic(association)

def fetch_blank_polymorphic(association)
  return nil unless association.collection?
  fetch_polymorphic_has_many_through_resource_records(association)
end

def fetch_non_polymorphic_related_through_resource_records(association)

def fetch_non_polymorphic_related_through_resource_records(association)
  association_instance = @resource.association(@relationship_name)
  related_resource_class = JSONAPI::ResourceLoader.find_for_model(association.klass)
  scope = related_resource_class.records.merge(association_instance.scope)
  association.collection? ? scope : scope.first
end

def fetch_polymorphic_has_many_through_resource_records(association)

def fetch_polymorphic_has_many_through_resource_records(association)
  association_instance = @resource.association(@relationship_name)
  related_resource_class = JSONAPI::ResourceLoader.find_for_model(association.klass)
  related_resource_class.records.merge(association_instance.scope)
end

def fetch_polymorphic_related_through_resource_records(association)

def fetch_polymorphic_related_through_resource_records(association)
  type_value = @resource.read_attribute(association.foreign_type)
  id_value = @resource.read_attribute(association.foreign_key)
  return fetch_blank_polymorphic(association) if type_value.blank? || id_value.blank?
  related_model_class = type_value.constantize
  related_resource_class = JSONAPI::ResourceLoader.find_for_model(related_model_class)
  record = related_resource_class.records.find(id_value)
  association.collection? ? Array(record) : record
end

def fetch_related_data(association)

def fetch_related_data(association)
  related = fetch_related_through_resource_records(association)
  return related unless association.collection? && related.respond_to?(:order)
  apply_sorting_to_relationship(related, association)
end

def fetch_related_through_resource_records(association)

def fetch_related_through_resource_records(association)
  if association.polymorphic?
    fetch_polymorphic_related_through_resource_records(association)
  else
    fetch_non_polymorphic_related_through_resource_records(association)
  end
end

def relationship_related_url

def relationship_related_url
  "/#{params[:resource_type]}/#{params[:id]}/#{params[:relationship_name]}"
end

def relationship_self_url

def relationship_self_url
  "/#{params[:resource_type]}/#{params[:id]}/relationships/#{params[:relationship_name]}"
end

def serialize_collection_relationship(related, association)

def serialize_collection_relationship(related, association)
  return [] if related.nil?
  related.map { |r| serialize_resource_identifier(r, association) }
end

def serialize_related(related, association)

def serialize_related(related, association)
  return serialize_collection_relationship(related, association) if association.collection?
  serialize_single_relationship(related, association) if related
end

def serialize_relationship_data

def serialize_relationship_data
  association = @resource.class.reflect_on_association(@relationship_name)
  return nil unless association
  related = fetch_related_data(association)
  serialize_related(related, association)
end

def serialize_relationship_links

def serialize_relationship_links
  {
    self: relationship_self_url,
    related: relationship_related_url,
  }
end

def serialize_relationship_meta

def serialize_relationship_meta
  relationship_def = find_relationship_definition
  return nil unless relationship_def
  relationship_def[:meta]
end

def serialize_resource_identifier(resource_instance, association)

def serialize_resource_identifier(resource_instance, association)
  RelationshipHelpers.serialize_resource_identifier(
    resource_instance,
    association:,
    resource_class: @resource_class,
  )
end

def serialize_single_relationship(related, association)

def serialize_single_relationship(related, association)
  serialize_resource_identifier(related, association)
end