mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-23 06:16:50 +00:00
Merge pull request #726 from rails-api/json-api-include-with-nested-has-many
Bugfix: include nested has_many associations
This commit is contained in:
commit
7592e838ee
@ -77,10 +77,13 @@ module ActiveModel
|
|||||||
resource_path = [parent, resource].compact.join('.')
|
resource_path = [parent, resource].compact.join('.')
|
||||||
if include_assoc? resource_path
|
if include_assoc? resource_path
|
||||||
plural_name = resource.to_s.pluralize.to_sym
|
plural_name = resource.to_s.pluralize.to_sym
|
||||||
attrs = attributes_for_serializer(serializer, @options)
|
attrs = [attributes_for_serializer(serializer, @options)].flatten
|
||||||
@top[:linked] ||= {}
|
@top[:linked] ||= {}
|
||||||
@top[:linked][plural_name] ||= []
|
@top[:linked][plural_name] ||= []
|
||||||
@top[:linked][plural_name].push attrs unless @top[:linked][plural_name].include? attrs
|
|
||||||
|
attrs.each do |attrs|
|
||||||
|
@top[:linked][plural_name].push(attrs) unless @top[:linked][plural_name].include?(attrs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
serializer.each_association do |name, association, opts|
|
serializer.each_association do |name, association, opts|
|
||||||
@ -91,9 +94,19 @@ module ActiveModel
|
|||||||
private
|
private
|
||||||
|
|
||||||
def attributes_for_serializer(serializer, options)
|
def attributes_for_serializer(serializer, options)
|
||||||
attributes = serializer.attributes(options)
|
if serializer.respond_to?(:each)
|
||||||
attributes[:id] = attributes[:id].to_s if attributes[:id]
|
result = []
|
||||||
attributes
|
serializer.each do |object|
|
||||||
|
attributes = object.attributes(options)
|
||||||
|
attributes[:id] = attributes[:id].to_s if attributes[:id]
|
||||||
|
result << attributes
|
||||||
|
end
|
||||||
|
else
|
||||||
|
result = serializer.attributes(options)
|
||||||
|
result[:id] = result[:id].to_s if result[:id]
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_assoc?(assoc)
|
def include_assoc?(assoc)
|
||||||
|
|||||||
@ -5,12 +5,15 @@ module ActionController
|
|||||||
class JsonApiLinkedTest < ActionController::TestCase
|
class JsonApiLinkedTest < ActionController::TestCase
|
||||||
class MyController < ActionController::Base
|
class MyController < ActionController::Base
|
||||||
def setup_post
|
def setup_post
|
||||||
|
@role1 = Role.new(id: 1, name: 'admin')
|
||||||
@author = Author.new(id: 1, name: 'Steve K.')
|
@author = Author.new(id: 1, name: 'Steve K.')
|
||||||
@author.posts = []
|
@author.posts = []
|
||||||
@author.bio = nil
|
@author.bio = nil
|
||||||
|
@author.roles = [@role1]
|
||||||
@author2 = Author.new(id: 2, name: 'Anonymous')
|
@author2 = Author.new(id: 2, name: 'Anonymous')
|
||||||
@author2.posts = []
|
@author2.posts = []
|
||||||
@author2.bio = nil
|
@author2.bio = nil
|
||||||
|
@author2.roles = []
|
||||||
@post = Post.new(id: 1, title: 'New Post', body: 'Body')
|
@post = Post.new(id: 1, title: 'New Post', body: 'Body')
|
||||||
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
||||||
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
||||||
@ -51,6 +54,13 @@ module ActionController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_resource_with_nested_has_many_include
|
||||||
|
with_json_api_adapter do
|
||||||
|
setup_post
|
||||||
|
render json: @post, include: 'author,author.roles'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def render_collection_without_include
|
def render_collection_without_include
|
||||||
with_json_api_adapter do
|
with_json_api_adapter do
|
||||||
setup_post
|
setup_post
|
||||||
@ -82,6 +92,22 @@ module ActionController
|
|||||||
assert_equal 'Steve K.', response['linked']['authors'].first['name']
|
assert_equal 'Steve K.', response['linked']['authors'].first['name']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_render_resource_with_nested_has_many_include
|
||||||
|
get :render_resource_with_nested_has_many_include
|
||||||
|
response = JSON.parse(@response.body)
|
||||||
|
expected_linked = {
|
||||||
|
"authors" => [{
|
||||||
|
"id" => "1",
|
||||||
|
"name" => "Steve K."
|
||||||
|
}],
|
||||||
|
"roles"=>[{
|
||||||
|
"id" => "1",
|
||||||
|
"name" => "admin"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
assert_equal expected_linked, response['linked']
|
||||||
|
end
|
||||||
|
|
||||||
def test_render_resource_with_nested_include
|
def test_render_resource_with_nested_include
|
||||||
get :render_resource_with_nested_include
|
get :render_resource_with_nested_include
|
||||||
response = JSON.parse(@response.body)
|
response = JSON.parse(@response.body)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ module ActiveModel
|
|||||||
def setup
|
def setup
|
||||||
@author = Author.new(name: 'Steve K.')
|
@author = Author.new(name: 'Steve K.')
|
||||||
@author.bio = nil
|
@author.bio = nil
|
||||||
|
@author.roles = nil
|
||||||
@first_post = Post.new(id: 1, title: 'Hello!!', body: 'Hello, world!!')
|
@first_post = Post.new(id: 1, title: 'Hello!!', body: 'Hello, world!!')
|
||||||
@second_post = Post.new(id: 2, title: 'New Post', body: 'Body')
|
@second_post = Post.new(id: 2, title: 'New Post', body: 'Body')
|
||||||
@author.posts = [@first_post, @second_post]
|
@author.posts = [@first_post, @second_post]
|
||||||
|
|||||||
@ -16,6 +16,7 @@ module ActiveModel
|
|||||||
@second_post.author = @author
|
@second_post.author = @author
|
||||||
@author.posts = [@first_post, @second_post]
|
@author.posts = [@first_post, @second_post]
|
||||||
@author.bio = @bio
|
@author.bio = @bio
|
||||||
|
@author.roles = []
|
||||||
@bio.author = @author
|
@bio.author = @author
|
||||||
|
|
||||||
@serializer = ArraySerializer.new([@first_post, @second_post])
|
@serializer = ArraySerializer.new([@first_post, @second_post])
|
||||||
|
|||||||
8
test/fixtures/poro.rb
vendored
8
test/fixtures/poro.rb
vendored
@ -40,6 +40,7 @@ Comment = Class.new(Model)
|
|||||||
Author = Class.new(Model)
|
Author = Class.new(Model)
|
||||||
Bio = Class.new(Model)
|
Bio = Class.new(Model)
|
||||||
Blog = Class.new(Model)
|
Blog = Class.new(Model)
|
||||||
|
Role = Class.new(Model)
|
||||||
|
|
||||||
PostSerializer = Class.new(ActiveModel::Serializer) do
|
PostSerializer = Class.new(ActiveModel::Serializer) do
|
||||||
attributes :title, :body, :id
|
attributes :title, :body, :id
|
||||||
@ -60,9 +61,16 @@ AuthorSerializer = Class.new(ActiveModel::Serializer) do
|
|||||||
attributes :id, :name
|
attributes :id, :name
|
||||||
|
|
||||||
has_many :posts, embed: :ids
|
has_many :posts, embed: :ids
|
||||||
|
has_many :roles, embed: :ids
|
||||||
belongs_to :bio
|
belongs_to :bio
|
||||||
end
|
end
|
||||||
|
|
||||||
|
RoleSerializer = Class.new(ActiveModel::Serializer) do
|
||||||
|
attributes :id, :name
|
||||||
|
|
||||||
|
belongs_to :author
|
||||||
|
end
|
||||||
|
|
||||||
BioSerializer = Class.new(ActiveModel::Serializer) do
|
BioSerializer = Class.new(ActiveModel::Serializer) do
|
||||||
attributes :id, :content
|
attributes :id, :content
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ module ActiveModel
|
|||||||
def setup
|
def setup
|
||||||
@author = Author.new(name: 'Steve K.')
|
@author = Author.new(name: 'Steve K.')
|
||||||
@author.bio = nil
|
@author.bio = nil
|
||||||
|
@author.roles = []
|
||||||
@post = Post.new({ title: 'New Post', body: 'Body' })
|
@post = Post.new({ title: 'New Post', body: 'Body' })
|
||||||
@comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' })
|
@comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' })
|
||||||
@post.comments = [@comment]
|
@post.comments = [@comment]
|
||||||
@ -42,6 +43,7 @@ module ActiveModel
|
|||||||
def test_has_many
|
def test_has_many
|
||||||
assert_equal(
|
assert_equal(
|
||||||
{ posts: { type: :has_many, options: { embed: :ids } },
|
{ posts: { type: :has_many, options: { embed: :ids } },
|
||||||
|
roles: { type: :has_many, options: { embed: :ids } },
|
||||||
bio: { type: :belongs_to, options: {} } },
|
bio: { type: :belongs_to, options: {} } },
|
||||||
@author_serializer.class._associations
|
@author_serializer.class._associations
|
||||||
)
|
)
|
||||||
@ -52,6 +54,9 @@ module ActiveModel
|
|||||||
elsif name == :bio
|
elsif name == :bio
|
||||||
assert_equal({}, options)
|
assert_equal({}, options)
|
||||||
assert_nil serializer
|
assert_nil serializer
|
||||||
|
elsif name == :roles
|
||||||
|
assert_equal({embed: :ids}, options)
|
||||||
|
assert_kind_of(ActiveModel::Serializer.config.array_serializer, serializer)
|
||||||
else
|
else
|
||||||
flunk "Unknown association: #{name}"
|
flunk "Unknown association: #{name}"
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user