lib/jsonapi/path_segment.rb
# frozen_string_literal: true
module JSONAPI
class PathSegment
def self.parse(source_resource_klass:, segment_string:, parse_fields: true)
first_part, last_part = segment_string.split('#', 2)
relationship = source_resource_klass._relationship(first_part)
if relationship
if last_part
unless relationship.resource_types.include?(last_part)
raise JSONAPI::Exceptions::InvalidRelationship.new(source_resource_klass._type, segment_string)
end
resource_klass = source_resource_klass.resource_klass_for(last_part)
end
return PathSegment::Relationship.new(relationship: relationship, resource_klass: resource_klass)
else
if last_part.blank? && parse_fields
return PathSegment::Field.new(resource_klass: source_resource_klass, field_name: first_part)
else
raise JSONAPI::Exceptions::InvalidRelationship.new(source_resource_klass._type, segment_string)
end
end
end
class Relationship
attr_reader :relationship, :resource_klass
def initialize(relationship:, resource_klass: nil)
@relationship = relationship
@resource_klass = resource_klass
end
def eql?(other)
other.is_a?(self.class) && relationship == other.relationship && resource_klass == other.resource_klass
end
def hash
[relationship, resource_klass].hash
end
def to_s
@resource_klass ? "#{relationship.parent_resource_klass._type}.#{relationship.name}##{resource_klass._type}" : "#{resource_klass._type}.#{relationship.name}"
end
def resource_klass
@resource_klass || relationship.resource_klass
end
def path_specified_resource_klass?
!@resource_klass.nil?
end
end
class Field
attr_reader :resource_klass, :field_name
def initialize(resource_klass:, field_name:)
@resource_klass = resource_klass
@field_name = field_name
end
def eql?(other)
other.is_a?(self.class) && field_name == other.field_name && resource_klass == other.resource_klass
end
def delegated_field_name
resource_klass._attribute_delegated_name(field_name)
end
def to_s
# :nocov:
"#{resource_klass._type}.#{field_name.to_s}"
# :nocov:
end
end
end
end