lib/jsonapi/resource_serializer.rb in jsonapi-resources-0.2.0 vs lib/jsonapi/resource_serializer.rb in jsonapi-resources-0.3.0.pre1

- old
+ new

@@ -25,40 +25,52 @@ # Converts a single resource, or an array of resources to a hash, conforming to the JSONAPI structure def serialize_to_hash(source) is_resource_collection = source.respond_to?(:to_ary) - @linked_objects = {} + @included_objects = {} requested_associations = parse_includes(@include) process_primary(source, requested_associations) - linked_objects = [] + included_objects = [] primary_objects = [] - @linked_objects.each_value do |objects| + @included_objects.each_value do |objects| objects.each_value do |object| if object[:primary] primary_objects.push(object[:object_hash]) else - linked_objects.push(object[:object_hash]) + included_objects.push(object[:object_hash]) end end end primary_hash = {data: is_resource_collection ? primary_objects : primary_objects[0]} - if linked_objects.size > 0 - primary_hash[:linked] = linked_objects + if included_objects.size > 0 + primary_hash[:included] = included_objects else primary_hash end primary_hash end def serialize_to_links_hash(source, requested_association) - {data: link_object(source, requested_association, true)} + if requested_association.is_a?(JSONAPI::Association::HasOne) + data = has_one_linkage(source, requested_association) + else + data = has_many_linkage(source, requested_association) + end + + { + links: { + self: self_link(source, requested_association), + related: related_link(source, requested_association) + }, + data: data + } end private # Convert an array of associated objects to include along with the primary document in the form of # ['comments','author','comments.tags','author.posts'] into a structure that tells what we need to include @@ -93,21 +105,21 @@ id = resource.id if already_serialized?(@primary_class_name, id) set_primary(@primary_class_name, id) end - add_linked_object(@primary_class_name, id, object_hash(resource, requested_associations), true) + add_included_object(@primary_class_name, id, object_hash(resource, requested_associations), true) end else resource = source id = resource.id # ToDo: See if this is actually needed # if already_serialized?(@primary_class_name, id) # set_primary(@primary_class_name, id) # end - add_linked_object(@primary_class_name, id, object_hash(source, requested_associations), true) + add_included_object(@primary_class_name, id, object_hash(source, requested_associations), true) end end # Returns a serialized hash for the source model, with def object_hash(source, requested_associations) @@ -183,22 +195,22 @@ resource = source.send(name) if resource id = resource.id associations_only = already_serialized?(type, id) if include_linkage && !associations_only - add_linked_object(type, id, object_hash(resource, ia[:include_related])) + add_included_object(type, id, object_hash(resource, ia[:include_related])) elsif include_linked_children || associations_only links_hash(resource, ia[:include_related]) end end elsif association.is_a?(JSONAPI::Association::HasMany) resources = source.send(name) resources.each do |resource| id = resource.id associations_only = already_serialized?(type, id) if include_linkage && !associations_only - add_linked_object(type, id, object_hash(resource, ia[:include_related])) + add_included_object(type, id, object_hash(resource, ia[:include_related])) elsif include_linked_children || associations_only links_hash(resource, ia[:include_related]) end end end @@ -215,40 +227,57 @@ "#{@base_url}/#{formatted_module_path(source)}#{@route_formatter.format(source.class._type.to_s)}/#{source.id}" end def already_serialized?(type, id) type = format_key(type) - return @linked_objects.key?(type) && @linked_objects[type].key?(id) + return @included_objects.key?(type) && @included_objects[type].key?(id) end def format_route(route) @route_formatter.format(route.to_s) end - def link_object_has_one(source, association) - route = association.name + def self_link(source, association) + "#{self_href(source)}/links/#{format_route(association.name)}" + end + def related_link(source, association) + "#{self_href(source)}/#{format_route(association.name)}" + end + + def has_one_linkage(source, association) + linkage = {} + linkage_id = foreign_key_value(source, association) + if linkage_id + linkage[:type] = format_route(association.type) + linkage[:id] = linkage_id + end + linkage + end + + def has_many_linkage(source, association) + linkage = [] + linkage_ids = foreign_key_value(source, association) + linkage_ids.each do |linkage_id| + linkage.append({type: format_route(association.type), id: linkage_id}) + end + linkage + end + + def link_object_has_one(source, association) link_object_hash = {} - link_object_hash[:self] = "#{self_href(source)}/links/#{format_route(route)}" - link_object_hash[:resource] = "#{self_href(source)}/#{format_route(route)}" - # ToDo: Get correct formatting figured out - link_object_hash[:type] = format_route(association.type) - link_object_hash[:id] = foreign_key_value(source, association) + link_object_hash[:self] = self_link(source, association) + link_object_hash[:related] = related_link(source, association) + link_object_hash[:linkage] = has_one_linkage(source, association) link_object_hash end def link_object_has_many(source, association, include_linkage) - route = association.name - link_object_hash = {} - link_object_hash[:self] = "#{self_href(source)}/links/#{format_route(route)}" - link_object_hash[:resource] = "#{self_href(source)}/#{format_route(route)}" - if include_linkage - # ToDo: Get correct formatting figured out - link_object_hash[:type] = format_route(association.type) - link_object_hash[:ids] = foreign_key_value(source, association) - end + link_object_hash[:self] = self_link(source, association) + link_object_hash[:related] = related_link(source, association) + link_object_hash[:linkage] = has_many_linkage(source, association) if include_linkage link_object_hash end def link_object(source, association, include_linkage = false) if association.is_a?(JSONAPI::Association::HasOne) @@ -271,26 +300,26 @@ end # Sets that an object should be included in the primary document of the response. def set_primary(type, id) type = format_key(type) - @linked_objects[type][id][:primary] = true + @included_objects[type][id][:primary] = true end # Collects the hashes for all objects processed by the serializer - def add_linked_object(type, id, object_hash, primary = false) + def add_included_object(type, id, object_hash, primary = false) type = format_key(type) - unless @linked_objects.key?(type) - @linked_objects[type] = {} + unless @included_objects.key?(type) + @included_objects[type] = {} end if already_serialized?(type, id) if primary set_primary(type, id) end else - @linked_objects[type].store(id, {primary: primary, object_hash: object_hash}) + @included_objects[type].store(id, {primary: primary, object_hash: object_hash}) end end def format_key(key) @key_formatter.format(key)