@@ -52,12 +52,13 @@ def initialize(serializer, options = {})
52
52
def serializable_hash ( options = nil )
53
53
options ||= { }
54
54
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?
61
62
62
63
ApiObjects ::JsonApi . add! ( hash )
63
64
@@ -66,6 +67,11 @@ def serializable_hash(options = nil)
66
67
hash [ :links ] . update ( instance_options [ :links ] )
67
68
end
68
69
70
+ if is_collection && serializer . paginated?
71
+ hash [ :links ] ||= { }
72
+ hash [ :links ] . update ( pagination_links_for ( serializer , options ) )
73
+ end
74
+
69
75
hash
70
76
end
71
77
@@ -80,37 +86,45 @@ def fragment_cache(cached_hash, non_cached_hash)
80
86
81
87
private
82
88
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 ) }
90
95
91
- included |= result [ : included]
92
- end
96
+ [ @primary , @ included]
97
+ end
93
98
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 )
96
102
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
100
108
end
101
109
102
- hash
110
+ true
103
111
end
104
112
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
109
118
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 )
112
126
113
- hash
127
+ process_relationships ( serializer , include_tree )
114
128
end
115
129
116
130
def resource_identifier_type_for ( serializer )
@@ -181,33 +195,6 @@ def relationships_for(serializer)
181
195
end
182
196
end
183
197
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
-
211
198
def links_for ( serializer )
212
199
serializer . _links . each_with_object ( { } ) do |( name , value ) , hash |
213
200
hash [ name ] = Link . new ( serializer , value ) . as_json
0 commit comments