From 398b5fab5d82f5385cfb930d5c77dc824298bf0b Mon Sep 17 00:00:00 2001 From: Benjamin Fleischer Date: Sun, 29 Oct 2017 19:40:04 -0500 Subject: [PATCH] Fix JSON:API: for_type_and_id should always inflect_type Should Serializer._type ever be inflected? Right now, it won't be, but association.serializer._type will be inflected. That's the current behavior. --- .../adapter/json_api/relationship.rb | 26 ++++++++++++------- .../adapter/json_api/resource_identifier.rb | 18 ++++++++----- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/lib/active_model_serializers/adapter/json_api/relationship.rb b/lib/active_model_serializers/adapter/json_api/relationship.rb index 5d06e5467..37aaeca3b 100644 --- a/lib/active_model_serializers/adapter/json_api/relationship.rb +++ b/lib/active_model_serializers/adapter/json_api/relationship.rb @@ -43,17 +43,16 @@ def data_for(association) end def data_for_one(association) - if association.belongs_to? && - parent_serializer.object.respond_to?(association.reflection.foreign_key) + if belongs_to_id_on_self?(association) id = parent_serializer.read_attribute_for_serialization(association.reflection.foreign_key) - if association.polymorphic? - # We can't infer resource type for polymorphic relationships from the serializer. - # We can ONLY know a polymorphic resource type by inspecting each resource. - serializer = association.lazy_association.serializer - type = serializer.json_key - else - type = association.reflection.type.to_s - end + type = + if association.polymorphic? + # We can't infer resource type for polymorphic relationships from the serializer. + # We can ONLY know a polymorphic resource type by inspecting each resource. + association.lazy_association.serializer.json_key + else + association.reflection.type.to_s + end ResourceIdentifier.for_type_with_id(type, id, serializable_resource_options) else # TODO(BF): Process relationship without evaluating lazy_association @@ -93,6 +92,13 @@ def meta_for(association) meta = association.meta meta.respond_to?(:call) ? parent_serializer.instance_eval(&meta) : meta end + + private + + def belongs_to_id_on_self?(association) + association.belongs_to? && + parent_serializer.object.respond_to?(association.reflection.foreign_key) + end end end end diff --git a/lib/active_model_serializers/adapter/json_api/resource_identifier.rb b/lib/active_model_serializers/adapter/json_api/resource_identifier.rb index 1c29263c7..3ff7118d5 100644 --- a/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +++ b/lib/active_model_serializers/adapter/json_api/resource_identifier.rb @@ -9,6 +9,7 @@ def self.type_for(serializer, serializer_type = nil, transform_options = {}) def self.for_type_with_id(type, id, options) return nil if id.blank? + type = inflect_type(type) { id: id.to_s, type: type_for(:no_class_needed, type, options) @@ -17,13 +18,17 @@ def self.for_type_with_id(type, id, options) def self.raw_type_from_serializer_object(object) class_name = object.class.name # should use model_name - serializer_type = class_name.underscore + raw_type = class_name.underscore + raw_type = inflect_type(raw_type) + raw_type + .gsub!('/'.freeze, ActiveModelSerializers.config.jsonapi_namespace_separator) + raw_type + end + + def self.inflect_type(type) singularize = ActiveModelSerializers.config.jsonapi_resource_type == :singular inflection = singularize ? :singularize : :pluralize - serializer_type = ActiveSupport::Inflector.public_send(inflection, serializer_type) - serializer_type - .gsub!('/'.freeze, ActiveModelSerializers.config.jsonapi_namespace_separator) - serializer_type + ActiveSupport::Inflector.public_send(inflection, type) end # {http://jsonapi.org/format/#document-resource-identifier-objects Resource Identifier Objects} @@ -44,7 +49,8 @@ def as_json private def type_for(serializer, transform_options) - self.class.type_for(serializer, serializer._type, transform_options) + serializer_type = serializer._type + self.class.type_for(serializer, serializer_type, transform_options) end def id_for(serializer)