adds polymorphic option to association definition which includes association type in serializer

regen gemlock

regen gemlock

better variable naming

rubocop fixes

adds to changelog

adds empty relationship and has_many polymorph tests

indent

test cleaning

-rubocop

rubocop

rubocop

rubocop

changelog

remove silly .DS

fix roque failure

fix
This commit is contained in:
cgmckeever 2016-05-15 13:19:37 -05:00
parent 6c321cd862
commit bbed12864d
6 changed files with 159 additions and 14 deletions

View File

@ -16,6 +16,7 @@ Features:
Fixes: Fixes:
- [#1700](https://github.com/rails-api/active_model_serializers/pull/1700) Support pagination link for Kaminari when no data is returned. (@iamnader) - [#1700](https://github.com/rails-api/active_model_serializers/pull/1700) Support pagination link for Kaminari when no data is returned. (@iamnader)
- [#1726](https://github.com/rails-api/active_model_serializers/pull/1726) Adds polymorphic option to association definition which includes association type/nesting in serializer (@cgmckeever)
Misc: Misc:
- [#1673](https://github.com/rails-api/active_model_serializers/pull/1673) Adds "How to" guide on using AMS with POROs (@DrSayre) - [#1673](https://github.com/rails-api/active_model_serializers/pull/1673) Adds "How to" guide on using AMS with POROs (@DrSayre)

View File

@ -52,6 +52,7 @@ Where:
- `if:` - `if:`
- `unless:` - `unless:`
- `virtual_value:` - `virtual_value:`
- `polymorphic:` defines if polymorphic relation type should be nested in serialized association.
- optional: `&block` is a context that returns the association's attributes. - optional: `&block` is a context that returns the association's attributes.
- prevents `association_name` method from being called. - prevents `association_name` method from being called.
- return value of block is used as the association value. - return value of block is used as the association value.

View File

@ -45,7 +45,14 @@ module ActiveModelSerializers
return unless association.serializer && association.serializer.object return unless association.serializer && association.serializer.object
opts = instance_options.merge(include: @include_tree[association.key]) opts = instance_options.merge(include: @include_tree[association.key])
Attributes.new(association.serializer, opts).serializable_hash(options) relationship_value = Attributes.new(association.serializer, opts).serializable_hash(options)
if association.options[:polymorphic] && relationship_value
polymorphic_type = association.serializer.object.class.name.underscore
relationship_value = { type: polymorphic_type, polymorphic_type.to_sym => relationship_value }
end
relationship_value
end end
# Set @cached_attributes # Set @cached_attributes

View File

@ -8,10 +8,17 @@ module ActiveModel
@employee = Employee.new(id: 42, name: 'Zoop Zoopler', email: 'zoop@example.com') @employee = Employee.new(id: 42, name: 'Zoop Zoopler', email: 'zoop@example.com')
@picture = @employee.pictures.new(id: 1, title: 'headshot-1.jpg') @picture = @employee.pictures.new(id: 1, title: 'headshot-1.jpg')
@picture.imageable = @employee @picture.imageable = @employee
end
@attributes_serialization = serializable(@picture, serializer: PolymorphicBelongsToSerializer) # uses default adapter: attributes def serialization(resource, adapter = :attributes)
@json_serialization = serializable(@picture, adapter: :json, serializer: PolymorphicBelongsToSerializer) serializable(resource, adapter: adapter, serializer: PolymorphicBelongsToSerializer).as_json
@json_api_serialization = serializable(@picture, adapter: :json_api, serializer: PolymorphicBelongsToSerializer) end
def tag_serialization(adapter = :attributes)
tag = PolyTag.new(id: 1, phrase: 'foo')
tag.object_tags << ObjectTag.new(id: 1, poly_tag_id: 1, taggable: @employee)
tag.object_tags << ObjectTag.new(id: 5, poly_tag_id: 1, taggable: @picture)
serializable(tag, adapter: adapter, serializer: PolymorphicTagSerializer, include: '*.*').as_json
end end
def test_attributes_serialization def test_attributes_serialization
@ -20,31 +27,123 @@ module ActiveModel
id: 1, id: 1,
title: 'headshot-1.jpg', title: 'headshot-1.jpg',
imageable: { imageable: {
id: 42, type: 'employee',
name: 'Zoop Zoopler' employee: {
id: 42,
name: 'Zoop Zoopler'
}
} }
} }
assert_equal(expected, @attributes_serialization.as_json) assert_equal(expected, serialization(@picture))
end end
def test_json_serializer def test_attributes_serialization_without_polymorphic_association
expected =
{
id: 2,
title: 'headshot-2.jpg',
imageable: nil
}
simple_picture = Picture.new(id: 2, title: 'headshot-2.jpg')
assert_equal(expected, serialization(simple_picture))
end
def test_attributes_serialization_with_polymorphic_has_many
expected =
{
id: 1,
phrase: 'foo',
object_tags: [
{
id: 1,
taggable: {
type: 'employee',
employee: {
id: 42
}
}
},
{
id: 5,
taggable: {
type: 'picture',
picture: {
id: 1
}
}
}
]
}
assert_equal(expected, tag_serialization)
end
def test_json_serialization
expected = expected =
{ {
picture: { picture: {
id: 1, id: 1,
title: 'headshot-1.jpg', title: 'headshot-1.jpg',
imageable: { imageable: {
id: 42, type: 'employee',
name: 'Zoop Zoopler' employee: {
id: 42,
name: 'Zoop Zoopler'
}
} }
} }
} }
assert_equal(expected, @json_serialization.as_json) assert_equal(expected, serialization(@picture, :json))
end end
def test_json_api_serializer def test_json_serialization_without_polymorphic_association
expected =
{
picture: {
id: 2,
title: 'headshot-2.jpg',
imageable: nil
}
}
simple_picture = Picture.new(id: 2, title: 'headshot-2.jpg')
assert_equal(expected, serialization(simple_picture, :json))
end
def test_json_serialization_with_polymorphic_has_many
expected =
{
poly_tag: {
id: 1,
phrase: 'foo',
object_tags: [
{
id: 1,
taggable: {
type: 'employee',
employee: {
id: 42
}
}
},
{
id: 5,
taggable: {
type: 'picture',
picture: {
id: 1
}
}
}
]
}
}
assert_equal(expected, tag_serialization(:json))
end
def test_json_api_serialization
expected = expected =
{ {
data: { data: {
@ -64,7 +163,7 @@ module ActiveModel
} }
} }
assert_equal(expected, @json_api_serialization.as_json) assert_equal(expected, serialization(@picture, :json_api))
end end
end end
end end

View File

@ -24,6 +24,16 @@ ActiveRecord::Schema.define do
t.string :email t.string :email
t.timestamp null: false t.timestamp null: false
end end
create_table :object_tags, force: true do |t|
t.string :poly_tag_id
t.string :taggable_type
t.string :taggable_id
t.timestamp null: false
end
create_table :poly_tags, force: true do |t|
t.string :phrase
t.timestamp null: false
end
create_table :pictures, force: true do |t| create_table :pictures, force: true do |t|
t.string :title t.string :title
t.string :imageable_type t.string :imageable_type

29
test/fixtures/poro.rb vendored
View File

@ -70,10 +70,21 @@ end
class Employee < ActiveRecord::Base class Employee < ActiveRecord::Base
has_many :pictures, as: :imageable has_many :pictures, as: :imageable
has_many :object_tags, as: :taggable
end
class ObjectTag < ActiveRecord::Base
belongs_to :poly_tag
belongs_to :taggable, polymorphic: true
end end
class Picture < ActiveRecord::Base class Picture < ActiveRecord::Base
belongs_to :imageable, polymorphic: true belongs_to :imageable, polymorphic: true
has_many :object_tags, as: :taggable
end
class PolyTag < ActiveRecord::Base
has_many :object_tags
end end
module Spam; end module Spam; end
@ -245,7 +256,23 @@ end
PolymorphicBelongsToSerializer = Class.new(ActiveModel::Serializer) do PolymorphicBelongsToSerializer = Class.new(ActiveModel::Serializer) do
attributes :id, :title attributes :id, :title
has_one :imageable, serializer: PolymorphicHasManySerializer has_one :imageable, serializer: PolymorphicHasManySerializer, polymorphic: true
end
PolymorphicSimpleSerializer = Class.new(ActiveModel::Serializer) do
attributes :id
end
PolymorphicObjectTagSerializer = Class.new(ActiveModel::Serializer) do
attributes :id
has_many :taggable, serializer: PolymorphicSimpleSerializer, polymorphic: true
end
PolymorphicTagSerializer = Class.new(ActiveModel::Serializer) do
attributes :id, :phrase
has_many :object_tags, serializer: PolymorphicObjectTagSerializer
end end
Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do