diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index e86078456..358c0e70b 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -18,6 +18,7 @@ # reified when subclassed to decorate a resource. module ActiveModel class Serializer + SERIALIZABLE_HASH_VALID_KEYS = Set.new([:only, :except, :methods, :include]) extend ActiveSupport::Autoload autoload :Adapter autoload :Null @@ -164,7 +165,7 @@ def serializable_hash(adapter_opts = nil) adapter_opts ||= {} adapter_opts = { include: '*', adapter: :attributes }.merge!(adapter_opts) adapter = ActiveModelSerializers::Adapter.create(self, adapter_opts) - adapter.serializable_hash(adapter_opts) + adapter.serializable_hash(adapter_opts.slice(SERIALIZABLE_HASH_VALID_KEYS)) end alias to_hash serializable_hash alias to_h serializable_hash diff --git a/lib/active_model_serializers/adapter/attributes.rb b/lib/active_model_serializers/adapter/attributes.rb index e2437c331..38446d846 100644 --- a/lib/active_model_serializers/adapter/attributes.rb +++ b/lib/active_model_serializers/adapter/attributes.rb @@ -8,7 +8,7 @@ def initialize(serializer, options = {}) end def serializable_hash(options = nil) - options ||= {} + options = super if serializer.respond_to?(:each) serializable_hash_for_collection(options) diff --git a/lib/active_model_serializers/adapter/base.rb b/lib/active_model_serializers/adapter/base.rb index 71eb59abf..baa5ac0d1 100644 --- a/lib/active_model_serializers/adapter/base.rb +++ b/lib/active_model_serializers/adapter/base.rb @@ -19,8 +19,8 @@ def cached_name @cached_name ||= self.class.name.demodulize.underscore end - def serializable_hash(_options = nil) - fail NotImplementedError, 'This is an abstract method. Should be implemented at the concrete adapter.' + def serializable_hash(options = nil) + (options ||= {}).slice(ActiveModel::Serializer::SERIALIZABLE_HASH_VALID_KEYS) end def as_json(options = nil) @@ -73,7 +73,8 @@ def key_transform(serialization_context) default_key_transform end - def transform_key_casing!(value, serialization_context) + def transform_key_casing!(value) + serialization_context = instance_options[:serialization_context] return value unless serialization_context transform = key_transform(serialization_context) KeyTransform.send(transform, value) diff --git a/lib/active_model_serializers/adapter/json.rb b/lib/active_model_serializers/adapter/json.rb index 7046d782c..486e1c57b 100644 --- a/lib/active_model_serializers/adapter/json.rb +++ b/lib/active_model_serializers/adapter/json.rb @@ -2,9 +2,9 @@ module ActiveModelSerializers module Adapter class Json < Base def serializable_hash(options = nil) - options ||= {} + options = super serialized_hash = { root => Attributes.new(serializer, instance_options).serializable_hash(options) } - transform_key_casing!(serialized_hash, options[:serialization_context]) + transform_key_casing!(serialized_hash) end end end diff --git a/lib/active_model_serializers/adapter/json_api.rb b/lib/active_model_serializers/adapter/json_api.rb index 3233121cb..853820f91 100644 --- a/lib/active_model_serializers/adapter/json_api.rb +++ b/lib/active_model_serializers/adapter/json_api.rb @@ -44,13 +44,13 @@ def default_key_transform # {http://jsonapi.org/format/#crud Requests are transactional, i.e. success or failure} # {http://jsonapi.org/format/#document-top-level data and errors MUST NOT coexist in the same document.} def serializable_hash(options = nil) - options ||= {} + options = super document = if serializer.success? success_document(options) else failure_document end - transform_key_casing!(document, options[:serialization_context]) + transform_key_casing!(document) end # {http://jsonapi.org/format/#document-top-level Primary data} @@ -499,7 +499,7 @@ def links_for(serializer) # prs: # https://github.com/rails-api/active_model_serializers/pull/1041 def pagination_links_for(serializer, options) - PaginationLinks.new(serializer.object, options[:serialization_context]).serializable_hash(options) + PaginationLinks.new(serializer.object, options).as_json end # {http://jsonapi.org/format/#document-meta Docment Meta} diff --git a/lib/active_model_serializers/adapter/json_api/pagination_links.rb b/lib/active_model_serializers/adapter/json_api/pagination_links.rb index cb3ed6ba0..6a187ec5e 100644 --- a/lib/active_model_serializers/adapter/json_api/pagination_links.rb +++ b/lib/active_model_serializers/adapter/json_api/pagination_links.rb @@ -6,12 +6,13 @@ class PaginationLinks attr_reader :collection, :context - def initialize(collection, context) + def initialize(collection, options) @collection = collection - @context = context + @options = options + @context = options.fetch(:serialization_context) end - def serializable_hash(options = {}) + def as_json per_page = collection.try(:per_page) || collection.try(:limit_value) || collection.size pages_from.each_with_object({}) do |(key, value), hash| params = query_parameters.merge(page: { number: value, size: per_page }).to_query @@ -20,6 +21,10 @@ def serializable_hash(options = {}) end end + protected + + attr_reader :options + private def pages_from diff --git a/lib/active_model_serializers/adapter/null.rb b/lib/active_model_serializers/adapter/null.rb index 6e690b1b0..9e5faf5cb 100644 --- a/lib/active_model_serializers/adapter/null.rb +++ b/lib/active_model_serializers/adapter/null.rb @@ -1,8 +1,7 @@ module ActiveModelSerializers module Adapter class Null < Base - # Since options param is not being used, underscored naming of the param - def serializable_hash(_options = nil) + def serializable_hash(*) {} end end