@@ -47,8 +47,6 @@ class Serializer
4747 #
4848 # So you can inspect reflections in your Adapters.
4949 class Reflection < Field
50- REFLECTION_OPTIONS = %i( key links polymorphic meta serializer virtual_value namespace ) . freeze
51-
5250 def initialize ( *)
5351 super
5452 options [ :links ] = { }
@@ -125,92 +123,6 @@ def collection?
125123 false
126124 end
127125
128- # Build association. This method is used internally to
129- # build serializer's association by its reflection.
130- #
131- # @param [Serializer] parent_serializer for given association
132- # @param [Hash{Symbol => Object}] parent_serializer_options
133- #
134- # @example
135- # # Given the following serializer defined:
136- # class PostSerializer < ActiveModel::Serializer
137- # has_many :comments, serializer: CommentSummarySerializer
138- # end
139- #
140- # # Then you instantiate your serializer
141- # post_serializer = PostSerializer.new(post, foo: 'bar') #
142- # # to build association for comments you need to get reflection
143- # comments_reflection = PostSerializer._reflections.detect { |r| r.name == :comments }
144- # # and #build_association
145- # comments_reflection.build_association(post_serializer, foo: 'bar')
146- #
147- # @api private
148- def build_association ( parent_serializer , parent_serializer_options , include_slice = { } )
149- reflection_options = settings . merge ( include_data : include_data? ( include_slice ) ) unless block?
150-
151- association_value = value ( parent_serializer , include_slice )
152- serializer_class = build_serializer_class ( association_value , parent_serializer , parent_serializer_options [ :namespace ] )
153-
154- reflection_options ||= settings . merge ( include_data : include_data? ( include_slice ) ) # Needs to be after association_value is evaluated unless reflection.block.nil?
155-
156- if serializer_class
157- if ( serializer = build_serializer! ( association_value , serializer_class , parent_serializer , parent_serializer_options ) )
158- reflection_options [ :serializer ] = serializer
159- else
160- # BUG: per #2027, JSON API resource relationships are only id and type, and hence either
161- # *require* a serializer or we need to be a little clever about figuring out the id/type.
162- # In either case, returning the raw virtual value will almost always be incorrect.
163- #
164- # Should be reflection_options[:virtual_value] or adapter needs to figure out what to do
165- # with an object that is non-nil and has no defined serializer.
166- reflection_options [ :virtual_value ] = association_value . try ( :as_json ) || association_value
167- end
168- elsif !association_value . nil? && !association_value . instance_of? ( Object )
169- reflection_options [ :virtual_value ] = association_value
170- end
171-
172- association_block = nil
173- reflection_options [ :reflection ] = self
174- reflection_options [ :parent_serializer ] = parent_serializer
175- reflection_options [ :parent_serializer_options ] = parent_serializer_options
176- reflection_options [ :include_slice ] = include_slice
177- Association . new ( name , reflection_options , block )
178- end
179-
180- protected
181-
182- # used in instance exec
183- attr_accessor :object , :scope
184-
185- def settings
186- options . dup . reject { |k , _ | !REFLECTION_OPTIONS . include? ( k ) }
187- end
188-
189- # Evaluation of the reflection.block will mutate options.
190- # So, the settings cannot be used until the block is evaluated.
191- # This means that each time the block is evaluated, it may set a new
192- # value in the reflection instance. This is not thread-safe.
193- # @example
194- # has_many :likes do
195- # meta liked: object.likes.any?
196- # include_data: object.loaded?
197- # end
198- def block?
199- !block . nil?
200- end
201-
202- def serializer?
203- options . key? ( :serializer )
204- end
205-
206- def serializer
207- options [ :serializer ]
208- end
209-
210- def namespace
211- options [ :namespace ]
212- end
213-
214126 def include_data? ( include_slice )
215127 include_data_setting = options [ :include_data_setting ]
216128 case include_data_setting
@@ -238,42 +150,39 @@ def value(serializer, include_slice)
238150 end
239151 end
240152
241- def build_serializer! ( association_value , serializer_class , parent_serializer , parent_serializer_options )
242- if collection?
243- build_association_collection_serializer ( parent_serializer , parent_serializer_options , association_value , serializer_class )
244- else
245- build_association_serializer ( parent_serializer , parent_serializer_options , association_value , serializer_class )
246- end
247- end
248-
249- def build_serializer_class ( association_value , parent_serializer , parent_serializer_namespace_option )
250- serializer_for_options = {
251- # Pass the parent's namespace onto the child serializer
252- namespace : namespace || parent_serializer_namespace_option
153+ # Build association. This method is used internally to
154+ # build serializer's association by its reflection.
155+ #
156+ # @param [Serializer] parent_serializer for given association
157+ # @param [Hash{Symbol => Object}] parent_serializer_options
158+ #
159+ # @example
160+ # # Given the following serializer defined:
161+ # class PostSerializer < ActiveModel::Serializer
162+ # has_many :comments, serializer: CommentSummarySerializer
163+ # end
164+ #
165+ # # Then you instantiate your serializer
166+ # post_serializer = PostSerializer.new(post, foo: 'bar') #
167+ # # to build association for comments you need to get reflection
168+ # comments_reflection = PostSerializer._reflections.detect { |r| r.name == :comments }
169+ # # and #build_association
170+ # comments_reflection.build_association(post_serializer, foo: 'bar')
171+ #
172+ # @api private
173+ def build_association ( parent_serializer , parent_serializer_options , include_slice = { } )
174+ association_options = {
175+ parent_serializer : parent_serializer ,
176+ parent_serializer_options : parent_serializer_options ,
177+ include_slice : include_slice
253178 }
254- serializer_for_options [ :serializer ] = serializer if serializer?
255- parent_serializer . class . serializer_for ( association_value , serializer_for_options )
179+ Association . new ( self , association_options )
256180 end
257181
258- # NOTE(BF): This serializer throw/catch should only happen when the serializer is a collection
259- # serializer.
260- #
261- # @return [ActiveModel::Serializer, nil]
262- def build_association_collection_serializer ( parent_serializer , parent_serializer_options , association_value , serializer_class )
263- catch ( :no_serializer ) do
264- build_association_serializer ( parent_serializer , parent_serializer_options , association_value , serializer_class )
265- end
266- end
182+ protected
267183
268- # @return [ActiveModel::Serializer, nil]
269- def build_association_serializer ( parent_serializer , parent_serializer_options , association_value , serializer_class )
270- # Make all the parent serializer instance options available to associations
271- # except ActiveModelSerializers-specific ones we don't want.
272- serializer_options = parent_serializer_options . except ( :serializer )
273- serializer_options [ :serializer_context_class ] = parent_serializer . class
274- serializer_options [ :serializer ] = serializer if serializer
275- serializer_class . new ( association_value , serializer_options )
276- end
184+ # used in instance exec
185+ attr_accessor :object , :scope
277186 end
278187 end
279188end
0 commit comments