From 73420cdc82b952c2a6590b2e05d528615b168f23 Mon Sep 17 00:00:00 2001 From: junwei Date: Thu, 10 Aug 2023 22:56:30 +0800 Subject: [PATCH] Prevent creation of unnecessary fieldset(mirror and revise changes from #2370) Co-authored-by: https://github.com/abcang --- lib/active_model_serializers/adapter/attributes.rb | 6 +++++- lib/active_model_serializers/adapter/json_api.rb | 5 +++-- test/serializers/attribute_test.rb | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/active_model_serializers/adapter/attributes.rb b/lib/active_model_serializers/adapter/attributes.rb index 3372e2be8..8e062e95a 100644 --- a/lib/active_model_serializers/adapter/attributes.rb +++ b/lib/active_model_serializers/adapter/attributes.rb @@ -5,7 +5,11 @@ module Adapter class Attributes < Base def initialize(*) super - instance_options[:fieldset] ||= ActiveModel::Serializer::Fieldset.new(fields_to_fieldset(instance_options.delete(:fields))) + + instance_options[:fieldset] ||= begin + fieldset = fields_to_fieldset(instance_options.delete(:fields)) + fieldset && ActiveModel::Serializer::Fieldset.new(fieldset) + end end def serializable_hash(options = nil) diff --git a/lib/active_model_serializers/adapter/json_api.rb b/lib/active_model_serializers/adapter/json_api.rb index 83c75ea82..6a0a2a905 100644 --- a/lib/active_model_serializers/adapter/json_api.rb +++ b/lib/active_model_serializers/adapter/json_api.rb @@ -53,7 +53,7 @@ def self.fragment_cache(cached_hash, non_cached_hash, root = true) def initialize(serializer, options = {}) super @include_directive = JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true) - @fieldset = options[:fieldset] || ActiveModel::Serializer::Fieldset.new(options.delete(:fields)) + @fieldset = options[:fieldset] || ((option_fields = options.delete(:fields)) && ActiveModel::Serializer::Fieldset.new(option_fields)) end # {http://jsonapi.org/format/#crud Requests are transactional, i.e. success or failure} @@ -348,7 +348,8 @@ def data_for(serializer, include_slice) data.tap do |resource_object| next if resource_object.nil? # NOTE(BF): the attributes are cached above, separately from the relationships, below. - requested_associations = fieldset.fields_for(resource_object[:type]) || '*' + requested_fields = fieldset && fieldset.fields_for(resource_object[:type]) + requested_associations = requested_fields || '*' relationships = relationships_for(serializer, requested_associations, include_slice) resource_object[:relationships] = relationships if relationships.any? end diff --git a/test/serializers/attribute_test.rb b/test/serializers/attribute_test.rb index 41386ea59..239a7d9bf 100644 --- a/test/serializers/attribute_test.rb +++ b/test/serializers/attribute_test.rb @@ -27,6 +27,20 @@ def test_attribute_inheritance_with_key assert_equal({ id: 1, title: 'AMS Hints' }, adapter.serializable_hash) end + def test_attribute_initialization_with_empty_fields + inherited_klass = Class.new(AlternateBlogSerializer) + blog_serializer = inherited_klass.new(@blog) + adapter = ActiveModelSerializers::Adapter::Attributes.new(blog_serializer, {fieldset: nil, fields: nil}) + assert_nil(adapter.instance_options[:fieldset]) + end + + def test_attribute_initialization_with_present_fields + inherited_klass = Class.new(AlternateBlogSerializer) + blog_serializer = inherited_klass.new(@blog) + adapter = ActiveModelSerializers::Adapter::Attributes.new(blog_serializer, {fieldset: nil, fields: [:id]}) + assert_equal(ActiveModel::Serializer::Fieldset, adapter.instance_options[:fieldset].class) + end + def test_multiple_calls_with_the_same_attribute serializer_class = Class.new(ActiveModel::Serializer) do attribute :title