77require 'active_model/serializer/fieldset'
88require 'active_model/serializer/lint'
99
10+ # ActiveModel::Serializer is an abstract class that is
11+ # reified when subclassed to decorate a resource.
1012module ActiveModel
1113 class Serializer
1214 include Configuration
@@ -44,19 +46,28 @@ def self.digest_caller_file(caller_line)
4446
4547 with_options instance_writer : false , instance_reader : false do |serializer |
4648 class_attribute :_type , instance_reader : true
47- class_attribute :_attributes
49+ class_attribute :_attributes # @api private : names of attribute methods, @see Serializer#attribute
4850 self . _attributes ||= [ ]
49- class_attribute :_attributes_keys
51+ class_attribute :_attributes_keys # @api private : maps attribute value to explict key name, @see Serializer#attribute
5052 self . _attributes_keys ||= { }
51- serializer . class_attribute :_cache
52- serializer . class_attribute :_fragmented
53- serializer . class_attribute :_cache_key
54- serializer . class_attribute :_cache_only
55- serializer . class_attribute :_cache_except
56- serializer . class_attribute :_cache_options
57- serializer . class_attribute :_cache_digest
53+ serializer . class_attribute :_cache # @api private : the cache object
54+ serializer . class_attribute :_fragmented # @api private : @see ::fragmented
55+ serializer . class_attribute :_cache_key # @api private : when present, is first item in cache_key
56+ serializer . class_attribute :_cache_only # @api private : when fragment caching, whitelists cached_attributes. Cannot combine with except
57+ serializer . class_attribute :_cache_except # @api private : when fragment caching, blacklists cached_attributes. Cannot combine with only
58+ serializer . class_attribute :_cache_options # @api private : used by CachedSerializer, passed to _cache.fetch
59+ # _cache_options include:
60+ # expires_in
61+ # compress
62+ # force
63+ # race_condition_ttl
64+ # Passed to ::_cache as
65+ # serializer._cache.fetch(cache_key, @klass._cache_options)
66+ serializer . class_attribute :_cache_digest # @api private : Generated
5867 end
5968
69+ # Serializers inherit _attributes and _attributes_keys.
70+ # Generates a unique digest for each serializer at load.
6071 def self . inherited ( base )
6172 caller_line = caller . first
6273 base . _attributes = _attributes . dup
@@ -65,10 +76,16 @@ def self.inherited(base)
6576 super
6677 end
6778
79+ # @example
80+ # class AdminAuthorSerializer < ActiveModel::Serializer
81+ # type 'authors'
6882 def self . type ( type )
6983 self . _type = type
7084 end
7185
86+ # @example
87+ # class AdminAuthorSerializer < ActiveModel::Serializer
88+ # attributes :id, :name, :recent_edits
7289 def self . attributes ( *attrs )
7390 attrs = attrs . first if attrs . first . class == Array
7491
@@ -77,6 +94,14 @@ def self.attributes(*attrs)
7794 end
7895 end
7996
97+ # @example
98+ # class AdminAuthorSerializer < ActiveModel::Serializer
99+ # attributes :id, :recent_edits
100+ # attribute :name, key: :title
101+ #
102+ # def recent_edits
103+ # object.edits.last(5)
104+ # enr
80105 def self . attribute ( attr , options = { } )
81106 key = options . fetch ( :key , attr )
82107 _attributes_keys [ attr ] = { key : key } if key != attr
@@ -89,11 +114,35 @@ def self.attribute(attr, options = {})
89114 end
90115 end
91116
117+ # @api private
118+ # Used by FragmentCache on the CachedSerializer
119+ # to call attribute methods on the fragmented cached serializer.
92120 def self . fragmented ( serializer )
93121 self . _fragmented = serializer
94122 end
95123
96124 # Enables a serializer to be automatically cached
125+ #
126+ # Sets +::_cache+ object to <tt>ActionController::Base.cache_store</tt>
127+ # when Rails.configuration.action_controller.perform_caching
128+ #
129+ # @params options [Hash] with valid keys:
130+ # key : @see ::_cache_key
131+ # only : @see ::_cache_only
132+ # except : @see ::_cache_except
133+ # skip_digest : does not include digest in cache_key
134+ # all else : @see ::_cache_options
135+ #
136+ # @example
137+ # class PostSerializer < ActiveModel::Serializer
138+ # cache key: 'post', expires_in: 3.hours
139+ # attributes :title, :body
140+ #
141+ # has_many :comments
142+ # end
143+ #
144+ # @todo require less code comments. See
145+ # https://github.com/rails-api/active_model_serializers/pull/1249#issuecomment-146567837
97146 def self . cache ( options = { } )
98147 self . _cache = ActionController ::Base . cache_store if Rails . configuration . action_controller . perform_caching
99148 self . _cache_key = options . delete ( :key )
@@ -102,6 +151,13 @@ def self.cache(options = {})
102151 self . _cache_options = ( options . empty? ) ? nil : options
103152 end
104153
154+ # @param resource [ActiveRecord::Base, ActiveModelSerializers::Model]
155+ # @return [ActiveModel::Serializer]
156+ # Preferentially returns
157+ # 1. resource.serializer
158+ # 2. ArraySerializer when resource is a collection
159+ # 3. options[:serializer]
160+ # 4. lookup serializer when resource is a Class
105161 def self . serializer_for ( resource , options = { } )
106162 if resource . respond_to? ( :serializer_class )
107163 resource . serializer_class
@@ -117,6 +173,8 @@ def self.adapter
117173 ActiveModel ::Serializer ::Adapter . lookup ( config . adapter )
118174 end
119175
176+ # Used to cache serializer name => serializer class
177+ # when looked up by Serializer.get_serializer_for.
120178 def self . serializers_cache
121179 @serializers_cache ||= ThreadSafe ::Cache . new
122180 end
@@ -136,6 +194,11 @@ def self.serializer_lookup_chain_for(klass)
136194 end
137195
138196 # @api private
197+ # Find a serializer from a class and caches the lookup.
198+ # Preferentially retuns:
199+ # 1. class name appended with "Serializer"
200+ # 2. try again with superclass, if present
201+ # 3. nil
139202 def self . get_serializer_for ( klass )
140203 serializers_cache . fetch_or_store ( klass ) do
141204 # NOTE(beauby): When we drop 1.9.3 support we can lazify the map for perfs.
@@ -151,6 +214,9 @@ def self.get_serializer_for(klass)
151214
152215 attr_accessor :object , :root , :scope
153216
217+ # `scope_name` is set as :current_user by default in the controller.
218+ # If the instance does not have a method named `scope_name`, it
219+ # defines the method so that it calls the +scope+.
154220 def initialize ( object , options = { } )
155221 self . object = object
156222 self . instance_options = options
@@ -165,10 +231,13 @@ def initialize(object, options = {})
165231 end
166232 end
167233
234+ # Used by adapter as resource root.
168235 def json_key
169236 root || object . class . model_name . to_s . underscore
170237 end
171238
239+ # Return the +attributes+ of +object+ as presented
240+ # by the serializer.
172241 def attributes
173242 attributes = self . class . _attributes . dup
174243
0 commit comments