@@ -52,12 +52,13 @@ def initialize(serializer, options = {})
5252 def serializable_hash ( options = nil )
5353 options ||= { }
5454
55- hash =
56- if serializer . respond_to? ( :each )
57- serializable_hash_for_collection ( options )
58- else
59- serializable_hash_for_single_resource
60- end
55+ is_collection = serializer . respond_to? ( :each )
56+ serializers = is_collection ? serializer : [ serializer ]
57+ primary_data , included = resource_objects_for ( serializers )
58+
59+ hash = { }
60+ hash [ :data ] = is_collection ? primary_data : primary_data [ 0 ]
61+ hash [ :included ] = included if included . any?
6162
6263 ApiObjects ::JsonApi . add! ( hash )
6364
@@ -66,6 +67,11 @@ def serializable_hash(options = nil)
6667 hash [ :links ] . update ( instance_options [ :links ] )
6768 end
6869
70+ if is_collection && serializer . paginated?
71+ hash [ :links ] ||= { }
72+ hash [ :links ] . update ( pagination_links_for ( serializer , options ) )
73+ end
74+
6975 hash
7076 end
7177
@@ -80,37 +86,45 @@ def fragment_cache(cached_hash, non_cached_hash)
8086
8187 private
8288
83- def serializable_hash_for_collection ( options )
84- hash = { data : [ ] }
85- included = [ ]
86- serializer . each do |s |
87- result = self . class . new ( s , instance_options . merge ( fieldset : fieldset ) ) . serializable_hash ( options )
88- hash [ :data ] << result [ :data ]
89- next unless result [ :included ]
89+ def resource_objects_for ( serializers )
90+ @primary = [ ]
91+ @included = [ ]
92+ @resource_identifiers = Set . new
93+ serializers . each { |serializer | process_resource ( serializer , true ) }
94+ serializers . each { |serializer | process_relationships ( serializer , @include_tree ) }
9095
91- included |= result [ : included]
92- end
96+ [ @primary , @ included]
97+ end
9398
94- included . delete_if { |resource | hash [ :data ] . include? ( resource ) }
95- hash [ :included ] = included if included . any?
99+ def process_resource ( serializer , primary )
100+ resource_identifier = resource_identifier_for ( serializer )
101+ return false unless @resource_identifiers . add? ( resource_identifier )
96102
97- if serializer . paginated?
98- hash [ :links ] ||= { }
99- hash [ :links ] . update ( pagination_links_for ( serializer , options ) )
103+ resource_object = resource_object_for ( serializer )
104+ if primary
105+ @primary << resource_object
106+ else
107+ @included << resource_object
100108 end
101109
102- hash
110+ true
103111 end
104112
105- def serializable_hash_for_single_resource
106- primary_data = resource_object_for ( serializer )
107-
108- hash = { data : primary_data }
113+ def process_relationships ( serializer , include_tree )
114+ serializer . associations ( include_tree ) . each do |association |
115+ process_relationship ( association . serializer , include_tree [ association . key ] )
116+ end
117+ end
109118
110- included = included_resources ( @include_tree , [ primary_data ] )
111- hash [ :included ] = included if included . any?
119+ def process_relationship ( serializer , include_tree )
120+ if serializer . respond_to? ( :each )
121+ serializer . each { |s | process_relationship ( s , include_tree ) }
122+ return
123+ end
124+ return unless serializer && serializer . object
125+ return unless process_resource ( serializer , false )
112126
113- hash
127+ process_relationships ( serializer , include_tree )
114128 end
115129
116130 def resource_identifier_type_for ( serializer )
@@ -181,33 +195,6 @@ def relationships_for(serializer)
181195 end
182196 end
183197
184- def included_resources ( include_tree , primary_data )
185- included = [ ]
186-
187- serializer . associations ( include_tree ) . each do |association |
188- add_included_resources_for ( association . serializer , include_tree [ association . key ] , primary_data , included )
189- end
190-
191- included
192- end
193-
194- def add_included_resources_for ( serializer , include_tree , primary_data , included )
195- if serializer . respond_to? ( :each )
196- serializer . each { |s | add_included_resources_for ( s , include_tree , primary_data , included ) }
197- else
198- return unless serializer && serializer . object
199-
200- resource_object = resource_object_for ( serializer )
201-
202- return if included . include? ( resource_object ) || primary_data . include? ( resource_object )
203- included . push ( resource_object )
204-
205- serializer . associations ( include_tree ) . each do |association |
206- add_included_resources_for ( association . serializer , include_tree [ association . key ] , primary_data , included )
207- end
208- end
209- end
210-
211198 def links_for ( serializer )
212199 serializer . _links . each_with_object ( { } ) do |( name , value ) , hash |
213200 hash [ name ] = Link . new ( serializer , value ) . as_json
0 commit comments