diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 693ec316..520e9d6a 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -83,11 +83,9 @@ module ActiveModel @top[:linked][plural_name].push attrs unless @top[:linked][plural_name].include? attrs end - unless serializer.respond_to?(:each) - serializer.each_association do |name, association, opts| - add_linked(name, association, resource) if association - end - end + serializer.each_association do |name, association, opts| + add_linked(name, association, resource_path) if association + end if include_nested_assoc? resource_path end private @@ -98,8 +96,20 @@ module ActiveModel attributes end - def include_assoc? assoc - @options[:include] && @options[:include].split(',').include?(assoc.to_s) + def include_assoc?(assoc) + return false unless @options[:include] + check_assoc("#{assoc}$") + end + + def include_nested_assoc?(assoc) + return false unless @options[:include] + check_assoc("#{assoc}.") + end + + def check_assoc(assoc) + @options[:include].split(',').any? do |s| + s.match(/^#{assoc.gsub('.', '\.')}/) + end end end end diff --git a/test/action_controller/json_api_linked_test.rb b/test/action_controller/json_api_linked_test.rb index f02e90e2..0770c78d 100644 --- a/test/action_controller/json_api_linked_test.rb +++ b/test/action_controller/json_api_linked_test.rb @@ -7,8 +7,10 @@ module ActionController def setup_post @author = Author.new(id: 1, name: 'Steve K.') @author.posts = [] + @author.bio = nil @author2 = Author.new(id: 2, name: 'Anonymous') @author2.posts = [] + @author2.bio = nil @post = Post.new(id: 1, title: 'New Post', body: 'Body') @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT') diff --git a/test/adapter/json_api/belongs_to_test.rb b/test/adapter/json_api/belongs_to_test.rb index e25a71d8..f18226af 100644 --- a/test/adapter/json_api/belongs_to_test.rb +++ b/test/adapter/json_api/belongs_to_test.rb @@ -7,6 +7,7 @@ module ActiveModel class BelongsToTest < Minitest::Test def setup @author = Author.new(id: 1, name: 'Steve K.') + @author.bio = nil @post = Post.new(id: 42, title: 'New Post', body: 'Body') @anonymous_post = Post.new(id: 43, title: 'Hello!!', body: 'Hello, world!!') @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') diff --git a/test/adapter/json_api/collection_test.rb b/test/adapter/json_api/collection_test.rb index 922103ea..a48e66b0 100644 --- a/test/adapter/json_api/collection_test.rb +++ b/test/adapter/json_api/collection_test.rb @@ -7,6 +7,7 @@ module ActiveModel class CollectionTest < Minitest::Test def setup @author = Author.new(id: 1, name: 'Steve K.') + @author.bio = nil @first_post = Post.new(id: 1, title: 'Hello!!', body: 'Hello, world!!') @second_post = Post.new(id: 2, title: 'New Post', body: 'Body') @first_post.comments = [] diff --git a/test/adapter/json_api/has_many_embed_ids_test.rb b/test/adapter/json_api/has_many_embed_ids_test.rb index 4690e3c6..8b3c0218 100644 --- a/test/adapter/json_api/has_many_embed_ids_test.rb +++ b/test/adapter/json_api/has_many_embed_ids_test.rb @@ -7,6 +7,7 @@ module ActiveModel class HasManyEmbedIdsTest < Minitest::Test def setup @author = Author.new(name: 'Steve K.') + @author.bio = nil @first_post = Post.new(id: 1, title: 'Hello!!', body: 'Hello, world!!') @second_post = Post.new(id: 2, title: 'New Post', body: 'Body') @author.posts = [@first_post, @second_post] diff --git a/test/adapter/json_api/has_many_test.rb b/test/adapter/json_api/has_many_test.rb index 975c5b63..6ded298a 100644 --- a/test/adapter/json_api/has_many_test.rb +++ b/test/adapter/json_api/has_many_test.rb @@ -8,6 +8,7 @@ module ActiveModel def setup @author = Author.new(id: 1, name: 'Steve K.') @author.posts = [] + @author.bio = nil @post = Post.new(id: 1, title: 'New Post', body: 'Body') @post_without_comments = Post.new(id: 2, title: 'Second Post', body: 'Second') @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT') diff --git a/test/adapter/json_api/linked_test.rb b/test/adapter/json_api/linked_test.rb index 160d3daa..2808e969 100644 --- a/test/adapter/json_api/linked_test.rb +++ b/test/adapter/json_api/linked_test.rb @@ -7,6 +7,7 @@ module ActiveModel class LinkedTest < Minitest::Test def setup @author = Author.new(id: 1, name: 'Steve K.') + @bio = Bio.new(id: 1, content: 'AMS Contributor') @first_post = Post.new(id: 1, title: 'Hello!!', body: 'Hello, world!!') @second_post = Post.new(id: 2, title: 'New Post', body: 'Body') @first_post.comments = [] @@ -14,9 +15,11 @@ module ActiveModel @first_post.author = @author @second_post.author = @author @author.posts = [@first_post, @second_post] + @author.bio = @bio + @bio.author = @author @serializer = ArraySerializer.new([@first_post, @second_post]) - @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: 'author,comments') + @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: 'author,author.bio,comments') end def test_include_multiple_posts_and_linked @@ -31,7 +34,10 @@ module ActiveModel { title: "Hello!!", body: "Hello, world!!", id: "1", links: { comments: ['1', '2'], author: "1" } }, { title: "New Post", body: "Body", id: "2", links: { comments: [], :author => "1" } } ], @adapter.serializable_hash[:posts]) - assert_equal({ :comments => [{ :id => "1", :body => "ZOMG A COMMENT" }, { :id => "2", :body => "ZOMG ANOTHER COMMENT" }], :authors => [{ :id => "1", :name => "Steve K." }] }, @adapter.serializable_hash[:linked]) + assert_equal({ :comments => [{ :id => "1", :body => "ZOMG A COMMENT" }, + { :id => "2", :body => "ZOMG ANOTHER COMMENT" }], + :authors => [{ :id => "1", :name => "Steve K." }], + :bios=>[{:id=>"1", :content=>"AMS Contributor"}] }, @adapter.serializable_hash[:linked]) end end end diff --git a/test/fixtures/poro.rb b/test/fixtures/poro.rb index 7d8d57b4..07ce073e 100644 --- a/test/fixtures/poro.rb +++ b/test/fixtures/poro.rb @@ -38,6 +38,7 @@ end Post = Class.new(Model) Comment = Class.new(Model) Author = Class.new(Model) +Bio = Class.new(Model) Blog = Class.new(Model) PostSerializer = Class.new(ActiveModel::Serializer) do @@ -59,6 +60,13 @@ AuthorSerializer = Class.new(ActiveModel::Serializer) do attributes :id, :name has_many :posts, embed: :ids + belongs_to :bio +end + +BioSerializer = Class.new(ActiveModel::Serializer) do + attributes :id, :content + + belongs_to :author end BlogSerializer = Class.new(ActiveModel::Serializer) do diff --git a/test/serializers/associations_test.rb b/test/serializers/associations_test.rb index 99162acc..65169496 100644 --- a/test/serializers/associations_test.rb +++ b/test/serializers/associations_test.rb @@ -26,6 +26,7 @@ module ActiveModel def setup @author = Author.new(name: 'Steve K.') + @author.bio = nil @post = Post.new({ title: 'New Post', body: 'Body' }) @comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' }) @post.comments = [@comment] @@ -39,11 +40,21 @@ module ActiveModel end def test_has_many - assert_equal({posts: {type: :has_many, options: {embed: :ids}}}, @author_serializer.class._associations) + assert_equal( + { posts: { type: :has_many, options: { embed: :ids } }, + bio: { type: :belongs_to, options: {} } }, + @author_serializer.class._associations + ) @author_serializer.each_association do |name, serializer, options| - assert_equal(:posts, name) - assert_equal({embed: :ids}, options) - assert_kind_of(ActiveModel::Serializer.config.array_serializer, serializer) + if name == :posts + assert_equal({embed: :ids}, options) + assert_kind_of(ActiveModel::Serializer.config.array_serializer, serializer) + elsif name == :bio + assert_equal({}, options) + assert_nil serializer + else + flunk "Unknown association: #{name}" + end end end