44require 'active_model/serializer/array_serializer'
55require 'active_model/serializer/error_serializer'
66require 'active_model/serializer/errors_serializer'
7- require 'active_model/serializer/concerns/associations'
8- require 'active_model/serializer/concerns/attributes'
97require 'active_model/serializer/concerns/caching'
10- require 'active_model/serializer/concerns/configuration'
11- require 'active_model/serializer/concerns/links'
12- require 'active_model/serializer/concerns/meta'
13- require 'active_model/serializer/concerns/type'
148require 'active_model/serializer/fieldset'
159require 'active_model/serializer/lint'
1610
@@ -23,13 +17,16 @@ class Serializer
2317 extend ActiveSupport ::Autoload
2418 autoload :Adapter
2519 autoload :Null
26- include Configuration
27- include Associations
28- include Attributes
20+ autoload :Attribute
21+ autoload :Association
22+ autoload :Reflection
23+ autoload :SingularReflection
24+ autoload :CollectionReflection
25+ autoload :BelongsToReflection
26+ autoload :HasOneReflection
27+ autoload :HasManyReflection
28+ include ActiveSupport ::Configurable
2929 include Caching
30- include Links
31- include Meta
32- include Type
3330
3431 # @param resource [ActiveRecord::Base, ActiveModelSerializers::Model]
3532 # @return [ActiveModel::Serializer]
@@ -111,6 +108,200 @@ def self.serialization_adapter_instance
111108 @serialization_adapter_instance ||= ActiveModelSerializers ::Adapter ::Attributes
112109 end
113110
111+ # Configuration options may also be set in
112+ # Serializers and Adapters
113+ config . collection_serializer = ActiveModel ::Serializer ::CollectionSerializer
114+ config . serializer_lookup_enabled = true
115+
116+ # @deprecated Use {#config.collection_serializer=} instead of this. Is
117+ # compatibilty layer for ArraySerializer.
118+ def config . array_serializer = ( collection_serializer )
119+ self . collection_serializer = collection_serializer
120+ end
121+
122+ # @deprecated Use {#config.collection_serializer} instead of this. Is
123+ # compatibilty layer for ArraySerializer.
124+ def config . array_serializer
125+ collection_serializer
126+ end
127+
128+ config . default_includes = '*'
129+ config . adapter = :attributes
130+ config . key_transform = nil
131+ config . jsonapi_pagination_links_enabled = true
132+ config . jsonapi_resource_type = :plural
133+ config . jsonapi_namespace_separator = '-' . freeze
134+ config . jsonapi_version = '1.0'
135+ config . jsonapi_toplevel_meta = { }
136+ # Make JSON API top-level jsonapi member opt-in
137+ # ref: http://jsonapi.org/format/#document-top-level
138+ config . jsonapi_include_toplevel_object = false
139+ config . include_data_default = true
140+
141+ # For configuring how serializers are found.
142+ # This should be an array of procs.
143+ #
144+ # The priority of the output is that the first item
145+ # in the evaluated result array will take precedence
146+ # over other possible serializer paths.
147+ #
148+ # i.e.: First match wins.
149+ #
150+ # @example output
151+ # => [
152+ # "CustomNamespace::ResourceSerializer",
153+ # "ParentSerializer::ResourceSerializer",
154+ # "ResourceNamespace::ResourceSerializer" ,
155+ # "ResourceSerializer"]
156+ #
157+ # If CustomNamespace::ResourceSerializer exists, it will be used
158+ # for serialization
159+ config . serializer_lookup_chain = ActiveModelSerializers ::LookupChain ::DEFAULT . dup
160+
161+ config . schema_path = 'test/support/schemas'
162+
163+ with_options instance_writer : false , instance_reader : false do |serializer |
164+ serializer . class_attribute :_attributes_data # @api private
165+ self . _attributes_data ||= { }
166+ end
167+ with_options instance_writer : false , instance_reader : true do |serializer |
168+ serializer . class_attribute :_reflections
169+ self . _reflections ||= { }
170+ serializer . class_attribute :_links # @api private
171+ self . _links ||= { }
172+ serializer . class_attribute :_meta # @api private
173+ serializer . class_attribute :_type # @api private
174+ end
175+
176+ def self . inherited ( base )
177+ super
178+ base . _attributes_data = _attributes_data . dup
179+ base . _reflections = _reflections . dup
180+ base . _links = _links . dup
181+ end
182+
183+ # keys of attributes
184+ # @see Serializer::attribute
185+ def self . _attributes
186+ _attributes_data . keys
187+ end
188+
189+ # @example
190+ # class AdminAuthorSerializer < ActiveModel::Serializer
191+ # attributes :id, :name, :recent_edits
192+ def self . attributes ( *attrs )
193+ attrs = attrs . first if attrs . first . class == Array
194+
195+ attrs . each do |attr |
196+ attribute ( attr )
197+ end
198+ end
199+
200+ # @example
201+ # class AdminAuthorSerializer < ActiveModel::Serializer
202+ # attributes :id, :recent_edits
203+ # attribute :name, key: :title
204+ #
205+ # attribute :full_name do
206+ # "#{object.first_name} #{object.last_name}"
207+ # end
208+ #
209+ # def recent_edits
210+ # object.edits.last(5)
211+ # end
212+ def self . attribute ( attr , options = { } , &block )
213+ key = options . fetch ( :key , attr )
214+ _attributes_data [ key ] = Attribute . new ( attr , options , block )
215+ end
216+
217+ # @api private
218+ # maps attribute value to explicit key name
219+ # @see Serializer::attribute
220+ # @see ActiveModel::Serializer::Caching#fragmented_attributes
221+ def self . _attributes_keys
222+ _attributes_data
223+ . each_with_object ( { } ) do |( key , attr ) , hash |
224+ next if key == attr . name
225+ hash [ attr . name ] = { key : key }
226+ end
227+ end
228+
229+ # @param [Symbol] name of the association
230+ # @param [Hash<Symbol => any>] options for the reflection
231+ # @return [void]
232+ #
233+ # @example
234+ # has_many :comments, serializer: CommentSummarySerializer
235+ #
236+ def self . has_many ( name , options = { } , &block ) # rubocop:disable Style/PredicateName
237+ associate ( HasManyReflection . new ( name , options , block ) )
238+ end
239+
240+ # @param [Symbol] name of the association
241+ # @param [Hash<Symbol => any>] options for the reflection
242+ # @return [void]
243+ #
244+ # @example
245+ # belongs_to :author, serializer: AuthorSerializer
246+ #
247+ def self . belongs_to ( name , options = { } , &block )
248+ associate ( BelongsToReflection . new ( name , options , block ) )
249+ end
250+
251+ # @param [Symbol] name of the association
252+ # @param [Hash<Symbol => any>] options for the reflection
253+ # @return [void]
254+ #
255+ # @example
256+ # has_one :author, serializer: AuthorSerializer
257+ #
258+ def self . has_one ( name , options = { } , &block ) # rubocop:disable Style/PredicateName
259+ associate ( HasOneReflection . new ( name , options , block ) )
260+ end
261+
262+ # Add reflection and define {name} accessor.
263+ # @param [ActiveModel::Serializer::Reflection] reflection
264+ # @return [void]
265+ #
266+ # @api private
267+ def self . associate ( reflection )
268+ key = reflection . options [ :key ] || reflection . name
269+ self . _reflections [ key ] = reflection
270+ end
271+ private_class_method :associate
272+
273+ # Define a link on a serializer.
274+ # @example
275+ # link(:self) { resource_url(object) }
276+ # @example
277+ # link(:self) { "http://example.com/resource/#{object.id}" }
278+ # @example
279+ # link :resource, "http://example.com/resource"
280+ #
281+ def self . link ( name , value = nil , &block )
282+ _links [ name ] = block || value
283+ end
284+
285+ # Set the JSON API meta attribute of a serializer.
286+ # @example
287+ # class AdminAuthorSerializer < ActiveModel::Serializer
288+ # meta { stuff: 'value' }
289+ # @example
290+ # meta do
291+ # { comment_count: object.comments.count }
292+ # end
293+ def self . meta ( value = nil , &block )
294+ self . _meta = block || value
295+ end
296+
297+ # Set the JSON API type of a serializer.
298+ # @example
299+ # class AdminAuthorSerializer < ActiveModel::Serializer
300+ # type 'authors'
301+ def self . type ( type )
302+ self . _type = type && type . to_s
303+ end
304+
114305 attr_accessor :object , :root , :scope
115306
116307 # `scope_name` is set as :current_user by default in the controller.
@@ -131,6 +322,36 @@ def success?
131322 true
132323 end
133324
325+ # Return the +attributes+ of +object+ as presented
326+ # by the serializer.
327+ def attributes ( requested_attrs = nil , reload = false )
328+ @attributes = nil if reload
329+ @attributes ||= self . class . _attributes_data . each_with_object ( { } ) do |( key , attr ) , hash |
330+ next if attr . excluded? ( self )
331+ next unless requested_attrs . nil? || requested_attrs . include? ( key )
332+ hash [ key ] = attr . value ( self )
333+ end
334+ end
335+
336+ # @param [JSONAPI::IncludeDirective] include_directive (defaults to the
337+ # +default_include_directive+ config value when not provided)
338+ # @return [Enumerator<Association>]
339+ #
340+ def associations ( include_directive = ActiveModelSerializers . default_include_directive , include_slice = nil )
341+ include_slice ||= include_directive
342+ return unless object
343+
344+ Enumerator . new do |y |
345+ self . class . _reflections . values . each do |reflection |
346+ next if reflection . excluded? ( self )
347+ key = reflection . options . fetch ( :key , reflection . name )
348+ next unless include_directive . key? ( key )
349+
350+ y . yield reflection . build_association ( self , instance_options , include_slice )
351+ end
352+ end
353+ end
354+
134355 # @return [Hash] containing the attributes and first level
135356 # associations, similar to how ActiveModel::Serializers::JSON is used
136357 # in ActiveRecord::Base.
0 commit comments