diff --git a/lib/active_model/serializer.rb b/lib/active_model/serializer.rb index 5e56ec17..3a0abe9c 100644 --- a/lib/active_model/serializer.rb +++ b/lib/active_model/serializer.rb @@ -9,6 +9,7 @@ require 'active_model/serializer/configuration' require 'active_model/serializer/fieldset' require 'active_model/serializer/lint' require 'active_model/serializer/links' +require 'active_model/serializer/meta' require 'active_model/serializer/type' # ActiveModel::Serializer is an abstract class that is @@ -20,26 +21,10 @@ module ActiveModel include Attributes include Caching include Links + include Meta include Type require 'active_model/serializer/adapter' - with_options instance_writer: false, instance_reader: false do |serializer| - serializer.class_attribute :_meta # @api private : meta definition, @see Serializer#meta - end - - # Register a meta attribute for the corresponding resource. - # - # @param [Hash] hash Optional hash - # @param [Block] block Optional block - def self.meta(hash = nil, &block) - self._meta = - if !block.nil? - block - else - hash - end - end - # @param resource [ActiveRecord::Base, ActiveModelSerializers::Model] # @return [ActiveModel::Serializer] # Preferentially returns @@ -145,14 +130,6 @@ module ActiveModel end end - def meta - if self.class._meta.respond_to?(:call) - instance_eval(&self.class._meta) - else - self.class._meta - end - end - protected attr_accessor :instance_options diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index b72ec6e1..d5ceaa91 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -6,6 +6,7 @@ module ActiveModel autoload :PaginationLinks autoload :FragmentCache autoload :Link + autoload :Meta autoload :Deserialization # TODO: if we like this abstraction and other API objects to it, @@ -157,7 +158,7 @@ module ActiveModel links = links_for(serializer) resource_object[:links] = links if links.any? - meta = serializer.meta + meta = meta_for(serializer) resource_object[:meta] = meta unless meta.nil? resource_object @@ -220,6 +221,10 @@ module ActiveModel def pagination_links_for(serializer, options) JsonApi::PaginationLinks.new(serializer.object, options[:serialization_context]).serializable_hash(options) end + + def meta_for(serializer) + Meta.new(serializer).as_json + end end end end diff --git a/lib/active_model/serializer/adapter/json_api/meta.rb b/lib/active_model/serializer/adapter/json_api/meta.rb new file mode 100644 index 00000000..8fba8986 --- /dev/null +++ b/lib/active_model/serializer/adapter/json_api/meta.rb @@ -0,0 +1,29 @@ +module ActiveModel + class Serializer + module Adapter + class JsonApi + class Meta + def initialize(serializer) + @object = serializer.object + @scope = serializer.scope + + # Use the return value of the block unless it is nil. + if serializer._meta.respond_to?(:call) + @value = instance_eval(&serializer._meta) + else + @value = serializer._meta + end + end + + def as_json + @value + end + + protected + + attr_reader :object, :scope + end + end + end + end +end diff --git a/lib/active_model/serializer/meta.rb b/lib/active_model/serializer/meta.rb new file mode 100644 index 00000000..5160585e --- /dev/null +++ b/lib/active_model/serializer/meta.rb @@ -0,0 +1,29 @@ +module ActiveModel + class Serializer + module Meta + extend ActiveSupport::Concern + + included do + with_options instance_writer: false, instance_reader: true do |serializer| + serializer.class_attribute :_meta # @api private + end + + extend ActiveSupport::Autoload + end + + module ClassMethods + # Set the JSON API meta attribute of a serializer. + # @example + # class AdminAuthorSerializer < ActiveModel::Serializer + # meta { stuff: 'value' } + # @example + # meta do + # { comment_count: object.comments.count } + # end + def meta(value = nil, &block) + self._meta = block || value + end + end + end + end +end