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