From 13ef8fed1bbe6978632020f094e16e96c69b1ba5 Mon Sep 17 00:00:00 2001 From: Lucas Hosseini Date: Sat, 24 Oct 2015 20:22:55 +0200 Subject: [PATCH 1/2] Fix `fields` option to restrict relationships as well. --- .../serializer/adapter/json_api.rb | 5 +- test/adapter/json_api/belongs_to_test.rb | 2 +- test/adapter/json_api/collection_test.rb | 2 +- test/adapter/json_api/fields_test.rb | 89 +++++++++++++++++++ test/adapter/json_api/has_many_test.rb | 2 +- 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 test/adapter/json_api/fields_test.rb diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index 55f5b494..ff081b80 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -174,7 +174,10 @@ module ActiveModel end def relationships_for(serializer) - serializer.associations.each_with_object({}) do |association, hash| + resource_type = resource_identifier_type_for(serializer) + requested_associations = fieldset.try(:fields_for, resource_type) || '*' + include_tree = IncludeTree.from_include_args(requested_associations) + serializer.associations(include_tree).each_with_object({}) do |association, hash| hash[association.key] = { data: relationship_value_for(association.serializer, association.options) } end end diff --git a/test/adapter/json_api/belongs_to_test.rb b/test/adapter/json_api/belongs_to_test.rb index acf98f4f..394ef88c 100644 --- a/test/adapter/json_api/belongs_to_test.rb +++ b/test/adapter/json_api/belongs_to_test.rb @@ -56,7 +56,7 @@ module ActiveModel end def test_limiting_linked_post_fields - @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:post], fields: { post: [:title] }) + @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:post], fields: { post: [:title, :comments, :blog, :author] }) expected = [{ id: '42', type: 'posts', diff --git a/test/adapter/json_api/collection_test.rb b/test/adapter/json_api/collection_test.rb index d5946ee5..59c0e08d 100644 --- a/test/adapter/json_api/collection_test.rb +++ b/test/adapter/json_api/collection_test.rb @@ -60,7 +60,7 @@ module ActiveModel def test_limiting_fields actual = ActiveModel::SerializableResource.new( [@first_post, @second_post], adapter: :json_api, - fields: { posts: ['title'] }) + fields: { posts: %w(title comments blog author) }) .serializable_hash expected = [ { diff --git a/test/adapter/json_api/fields_test.rb b/test/adapter/json_api/fields_test.rb new file mode 100644 index 00000000..d7bab63a --- /dev/null +++ b/test/adapter/json_api/fields_test.rb @@ -0,0 +1,89 @@ +require 'test_helper' + +module ActiveModel + class Serializer + module Adapter + class JsonApi + class FieldsTest < Minitest::Test + Post = Class.new(::Model) + class PostSerializer < ActiveModel::Serializer + type 'posts' + attributes :title, :body + belongs_to :author + has_many :comments + end + + Author = Class.new(::Model) + class AuthorSerializer < ActiveModel::Serializer + type 'authors' + attributes :name, :birthday + end + + Comment = Class.new(::Model) + class CommentSerializer < ActiveModel::Serializer + type 'comments' + attributes :body + belongs_to :author + end + + def setup + @author = Author.new(id: 1, name: 'Lucas', birthday: '10.01.1990') + @comment1 = Comment.new(id: 7, body: 'cool', author: @author) + @comment2 = Comment.new(id: 12, body: 'awesome', author: @author) + @post = Post.new(id: 1337, title: 'Title 1', body: 'Body 1', + author: @author, comments: [@comment1, @comment2]) + @comment1.post = @post + @comment2.post = @post + end + + def test_fields_attributes + fields = { posts: [:title] } + hash = serializable(@post, adapter: :json_api, fields: fields).serializable_hash + expected = { + title: 'Title 1' + } + + assert_equal(expected, hash[:data][:attributes]) + end + + def test_fields_relationships + fields = { posts: [:author] } + hash = serializable(@post, adapter: :json_api, fields: fields).serializable_hash + expected = { + author: { + data: { + type: 'authors', + id: '1' + } + } + } + + assert_equal(expected, hash[:data][:relationships]) + end + + def test_fields_included + fields = { posts: [:author], comments: [:body] } + hash = serializable(@post, adapter: :json_api, fields: fields, include: 'comments').serializable_hash + expected = [ + { + type: 'comments', + id: '7', + attributes: { + body: 'cool' + } + }, { + type: 'comments', + id: '12', + attributes: { + body: 'awesome' + } + } + ] + + assert_equal(expected, hash[:included]) + end + end + end + end + end +end diff --git a/test/adapter/json_api/has_many_test.rb b/test/adapter/json_api/has_many_test.rb index 07453681..5b19e336 100644 --- a/test/adapter/json_api/has_many_test.rb +++ b/test/adapter/json_api/has_many_test.rb @@ -68,7 +68,7 @@ module ActiveModel end def test_limit_fields_of_linked_comments - @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:comments], fields: { comment: [:id] }) + @adapter = ActiveModel::Serializer::Adapter::JsonApi.new(@serializer, include: [:comments], fields: { comment: [:id, :post, :author] }) expected = [{ id: '1', type: 'comments', From b5aecfd1149e93870f83226f50b84081299f4b20 Mon Sep 17 00:00:00 2001 From: Lucas Hosseini Date: Sun, 25 Oct 2015 19:56:43 +0100 Subject: [PATCH 2/2] Initialize fieldset. --- lib/active_model/serializer/adapter/json_api.rb | 10 ++-------- lib/active_model/serializer/fieldset.rb | 4 ++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index ff081b80..6f43d5f3 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -44,13 +44,7 @@ module ActiveModel def initialize(serializer, options = {}) super @include_tree = IncludeTree.from_include_args(options[:include]) - - fields = options.delete(:fields) - if fields - @fieldset = ActiveModel::Serializer::Fieldset.new(fields) - else - @fieldset = options[:fieldset] - end + @fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields)) end def serializable_hash(options = nil) @@ -175,7 +169,7 @@ module ActiveModel def relationships_for(serializer) resource_type = resource_identifier_type_for(serializer) - requested_associations = fieldset.try(:fields_for, resource_type) || '*' + requested_associations = fieldset.fields_for(resource_type) || '*' include_tree = IncludeTree.from_include_args(requested_associations) serializer.associations(include_tree).each_with_object({}) do |association, hash| hash[association.key] = { data: relationship_value_for(association.serializer, association.options) } diff --git a/lib/active_model/serializer/fieldset.rb b/lib/active_model/serializer/fieldset.rb index 4f2211df..efa3187c 100644 --- a/lib/active_model/serializer/fieldset.rb +++ b/lib/active_model/serializer/fieldset.rb @@ -2,7 +2,7 @@ module ActiveModel class Serializer class Fieldset def initialize(fields) - @raw_fields = fields + @raw_fields = fields || {} end def fields @@ -21,7 +21,7 @@ module ActiveModel def parsed_fields if raw_fields.is_a?(Hash) - raw_fields.inject({}) { |h, (k, v)| h[k.to_sym] = v.map(&:to_sym); h } + raw_fields.each_with_object({}) { |(k, v), h| h[k.to_sym] = v.map(&:to_sym) } else {} end