Skip to content

Commit e348034

Browse files
authored
Merge pull request #2211 from rails-api/polymorphic_relationships_require_serializer_instance
JSON:API relationship tests no longer show v0.10.5 regression
2 parents 54d40c7 + a0de45a commit e348034

File tree

4 files changed

+83
-23
lines changed

4 files changed

+83
-23
lines changed

lib/active_model_serializers/adapter/json_api/relationship.rb

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,16 @@ def data_for(association)
4343
end
4444

4545
def data_for_one(association)
46-
if association.belongs_to? &&
47-
parent_serializer.object.respond_to?(association.reflection.foreign_key)
46+
if belongs_to_id_on_self?(association)
4847
id = parent_serializer.read_attribute_for_serialization(association.reflection.foreign_key)
49-
type = association.reflection.type.to_s
48+
type =
49+
if association.polymorphic?
50+
# We can't infer resource type for polymorphic relationships from the serializer.
51+
# We can ONLY know a polymorphic resource type by inspecting each resource.
52+
association.lazy_association.serializer.json_key
53+
else
54+
association.reflection.type.to_s
55+
end
5056
ResourceIdentifier.for_type_with_id(type, id, serializable_resource_options)
5157
else
5258
# TODO(BF): Process relationship without evaluating lazy_association
@@ -86,6 +92,11 @@ def meta_for(association)
8692
meta = association.meta
8793
meta.respond_to?(:call) ? parent_serializer.instance_eval(&meta) : meta
8894
end
95+
96+
def belongs_to_id_on_self?(association)
97+
association.belongs_to? &&
98+
parent_serializer.object.respond_to?(association.reflection.foreign_key)
99+
end
89100
end
90101
end
91102
end

lib/active_model_serializers/adapter/json_api/resource_identifier.rb

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,35 @@ module ActiveModelSerializers
22
module Adapter
33
class JsonApi
44
class ResourceIdentifier
5-
def self.type_for(class_name, serializer_type = nil, transform_options = {})
6-
if serializer_type
7-
raw_type = serializer_type
8-
else
9-
inflection =
10-
if ActiveModelSerializers.config.jsonapi_resource_type == :singular
11-
:singularize
12-
else
13-
:pluralize
14-
end
15-
16-
raw_type = class_name.underscore
17-
raw_type = ActiveSupport::Inflector.public_send(inflection, raw_type)
18-
raw_type
19-
.gsub!('/'.freeze, ActiveModelSerializers.config.jsonapi_namespace_separator)
20-
raw_type
21-
end
5+
def self.type_for(serializer, serializer_type = nil, transform_options = {})
6+
raw_type = serializer_type ? serializer_type : raw_type_from_serializer_object(serializer.object)
227
JsonApi.send(:transform_key_casing!, raw_type, transform_options)
238
end
249

2510
def self.for_type_with_id(type, id, options)
2611
return nil if id.blank?
12+
type = inflect_type(type)
2713
{
2814
id: id.to_s,
2915
type: type_for(:no_class_needed, type, options)
3016
}
3117
end
3218

19+
def self.raw_type_from_serializer_object(object)
20+
class_name = object.class.name # should use model_name
21+
raw_type = class_name.underscore
22+
raw_type = inflect_type(raw_type)
23+
raw_type
24+
.gsub!('/'.freeze, ActiveModelSerializers.config.jsonapi_namespace_separator)
25+
raw_type
26+
end
27+
28+
def self.inflect_type(type)
29+
singularize = ActiveModelSerializers.config.jsonapi_resource_type == :singular
30+
inflection = singularize ? :singularize : :pluralize
31+
ActiveSupport::Inflector.public_send(inflection, type)
32+
end
33+
3334
# {http://jsonapi.org/format/#document-resource-identifier-objects Resource Identifier Objects}
3435
def initialize(serializer, options)
3536
@id = id_for(serializer)
@@ -48,7 +49,8 @@ def as_json
4849
private
4950

5051
def type_for(serializer, transform_options)
51-
self.class.type_for(serializer.object.class.name, serializer._type, transform_options)
52+
serializer_type = serializer._type
53+
self.class.type_for(serializer, serializer_type, transform_options)
5254
end
5355

5456
def id_for(serializer)

test/adapter/polymorphic_test.rb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,53 @@ def test_json_api_serialization
165165

166166
assert_equal(expected, serialization(@picture, :json_api))
167167
end
168+
169+
def test_json_api_serialization_with_polymorphic_belongs_to
170+
expected = {
171+
data: {
172+
id: '1',
173+
type: 'poly-tags',
174+
attributes: { phrase: 'foo' },
175+
relationships: {
176+
:"object-tags" => {
177+
data: [
178+
{ id: '1', type: 'object-tags' },
179+
{ id: '5', type: 'object-tags' }
180+
]
181+
}
182+
}
183+
},
184+
included: [
185+
{
186+
id: '1',
187+
type: 'object-tags',
188+
relationships: {
189+
taggable: {
190+
data: { id: '42', type: 'employees' }
191+
}
192+
}
193+
},
194+
{
195+
id: '42',
196+
type: 'employees'
197+
},
198+
{
199+
id: '5',
200+
type: 'object-tags',
201+
relationships: {
202+
taggable: {
203+
data: { id: '1', type: 'pictures' }
204+
}
205+
}
206+
},
207+
{
208+
id: '1',
209+
type: 'pictures'
210+
}
211+
]
212+
}
213+
assert_equal(expected, tag_serialization(:json_api))
214+
end
168215
end
169216
end
170217
end

test/fixtures/active_record.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class ObjectTag < ActiveRecord::Base
8989
end
9090
class PolymorphicObjectTagSerializer < ActiveModel::Serializer
9191
attributes :id
92-
has_many :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
92+
belongs_to :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
9393
end
9494

9595
class PolyTag < ActiveRecord::Base
@@ -109,5 +109,5 @@ class PolymorphicHasManySerializer < ActiveModel::Serializer
109109
end
110110
class PolymorphicBelongsToSerializer < ActiveModel::Serializer
111111
attributes :id, :title
112-
has_one :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
112+
belongs_to :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
113113
end

0 commit comments

Comments
 (0)