Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes nested has_many links in JSONAPI #730

Merged
merged 1 commit into from
Nov 17, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions lib/active_model/serializer/adapter/json_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,30 @@ def add_link(resource, name, serializer)
end
end

def add_linked(resource_name, serializer, parent = nil)
def add_linked(resource_name, serializers, parent = nil)
serializers = Array(serializers) unless serializers.respond_to?(:each)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is 'unless ...' needed here? If serializers is already an Array, Array(serializers) would just retunr serilizers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, It can be Serializer or ArraySerializer. If it's Serializer, I convert to [Serializer] so I can treat them all equally, without the need for duplicating the logic, eg.

if serializer.respond_to?(:each)
  serializer.each  
    do something
  end
else
  do something
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, Array(array_serializer) would be wrong.


resource_path = [parent, resource_name].compact.join('.')

if include_assoc?(resource_path)
plural_name = serialized_object_type(serializer).pluralize.to_sym
attrs = [attributes_for_serializer(serializer, @options)].flatten
plural_name = serialized_object_type(serializers).pluralize.to_sym
@top[:linked] ||= {}
@top[:linked][plural_name] ||= []

attrs.each do |attrs|
serializers.each do |serializer|
attrs = attributes_for_serializer(serializer, @options)

add_resource_links(attrs, serializer, add_linked: false)

@top[:linked][plural_name].push(attrs) unless @top[:linked][plural_name].include?(attrs)
end
end

serializer.each_association do |name, association, opts|
add_linked(name, association, resource_path) if association
end if include_nested_assoc? resource_path
serializers.each do |serializer|
serializer.each_association do |name, association, opts|
add_linked(name, association, resource_path) if association
end if include_nested_assoc? resource_path
end
end

def attributes_for_serializer(serializer, options)
Expand Down Expand Up @@ -124,7 +129,7 @@ def serialized_object_type(serializer)
def add_resource_links(attrs, serializer, options = {})
options[:add_linked] = options.fetch(:add_linked, true)

Array(serializer).first.each_association do |name, association, opts|
serializer.each_association do |name, association, opts|
attrs[:links] ||= {}

if association.respond_to?(:each)
Expand Down
90 changes: 78 additions & 12 deletions test/adapter/json_api/linked_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,32 @@ class Adapter
class JsonApi
class LinkedTest < Minitest::Test
def setup
@author = Author.new(id: 1, name: 'Steve K.')
@bio = Bio.new(id: 1, content: 'AMS Contributor')
@author1 = Author.new(id: 1, name: 'Steve K.')
@author2 = Author.new(id: 2, name: 'Tenderlove')
@bio1 = Bio.new(id: 1, content: 'AMS Contributor')
@bio2 = Bio.new(id: 2, content: 'Rails Contributor')
@first_post = Post.new(id: 1, title: 'Hello!!', body: 'Hello, world!!')
@second_post = Post.new(id: 2, title: 'New Post', body: 'Body')
@third_post = Post.new(id: 3, title: 'Yet Another Post', body: 'Body')
@first_post.comments = []
@second_post.comments = []
@first_post.author = @author
@second_post.author = @author
@author.posts = [@first_post, @second_post]
@author.bio = @bio
@author.roles = []
@bio.author = @author
@first_post.author = @author1
@second_post.author = @author2
@third_post.author = @author1
@author1.posts = [@first_post, @third_post]
@author1.bio = @bio1
@author1.roles = []
@author2.posts = [@second_post]
@author2.bio = @bio2
@author2.roles = []
@bio1.author = @author1
@bio2.author = @author2
end

def test_include_multiple_posts_and_linked
@serializer = ArraySerializer.new([@first_post, @second_post])
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: 'author,author.bio,comments')
end

def test_include_multiple_posts_and_linked
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
@first_post.comments = [@first_comment, @second_comment]
Expand All @@ -33,7 +41,7 @@ def test_include_multiple_posts_and_linked
@second_comment.author = nil
assert_equal([
{ title: "Hello!!", body: "Hello, world!!", id: "1", links: { comments: ['1', '2'], author: "1" } },
{ title: "New Post", body: "Body", id: "2", links: { comments: [], :author => "1" } }
{ title: "New Post", body: "Body", id: "2", links: { comments: [], :author => "2" } }
], @adapter.serializable_hash[:posts])


Expand All @@ -57,17 +65,75 @@ def test_include_multiple_posts_and_linked
id: "1",
name: "Steve K.",
links: {
posts: ["1", "2"],
posts: ["1"],
roles: [],
bio: "1"
}
}, {
id: "2",
name: "Tenderlove",
links: {
posts: ["2"],
roles: [],
bio: "2"
}
}],
bios: [{
id: "1",
content: "AMS Contributor",
links: {
author: "1"
}
}, {
id: "2",
content: "Rails Contributor",
links: {
author: "2"
}
}]
}
assert_equal expected, @adapter.serializable_hash[:linked]
end

def test_include_multiple_posts_and_linked
@serializer = BioSerializer.new(@bio1)
@adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: 'author,author.posts')

@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
@first_post.comments = [@first_comment, @second_comment]
@third_post.comments = []
@first_comment.post = @first_post
@first_comment.author = nil
@second_comment.post = @first_post
@second_comment.author = nil

expected = {
authors: [{
id: "1",
name: "Steve K.",
links: {
posts: ["1", "3"],
roles: [],
bio: "1"
}
}],
posts: [{
title: "Hello!!",
body: "Hello, world!!",
id: "1",
links: {
comments: ["1", "2"],
author: "1"
}
}, {
title: "Yet Another Post",
body: "Body",
id: "3",
links: {
comments: [],
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bug was here. Before, comments was ["1", "2"], not [].

author: "1"
}
}]
}
assert_equal expected, @adapter.serializable_hash[:linked]
Expand Down