@@ -56,15 +56,29 @@ def initialize(serializer, options = {})
56
56
def serializable_hash ( options = nil )
57
57
options ||= { }
58
58
59
- hash =
60
- if serializer . respond_to? ( :each )
61
- serializable_hash_for_collection ( options )
59
+ is_collection = serializer . respond_to? ( :each )
60
+ resources = { }
61
+ process_resource ( serializer , @include_tree , true , resources )
62
+ primary_data , included = resources . each_with_object ( [ [ ] , [ ] ] ) do |( _ , resource ) , ( primary , included ) |
63
+ if resource [ :is_primary ]
64
+ primary . push ( resource . except ( :is_primary ) )
62
65
else
63
- serializable_hash_for_single_resource
66
+ included . push ( resource . except ( :is_primary ) )
64
67
end
68
+ end
69
+
70
+ hash = { }
71
+ hash [ :data ] = is_collection ? primary_data : primary_data . first
72
+
73
+ hash [ :included ] = included if included . any?
65
74
66
75
ApiObjects ::JsonApi . add! ( hash )
67
76
77
+ if is_collection && serializer . paginated?
78
+ hash [ :links ] ||= { }
79
+ hash [ :links ] . update ( links_for ( serializer , options ) )
80
+ end
81
+
68
82
if instance_options [ :links ]
69
83
hash [ :links ] ||= { }
70
84
hash [ :links ] . update ( instance_options [ :links ] )
@@ -84,38 +98,32 @@ def fragment_cache(cached_hash, non_cached_hash)
84
98
85
99
private
86
100
87
- def serializable_hash_for_collection ( options )
88
- hash = { data : [ ] }
89
- included = [ ]
90
- serializer . each do |s |
91
- result = self . class . new ( s , instance_options . merge ( fieldset : fieldset ) ) . serializable_hash ( options )
92
- hash [ :data ] << result [ :data ]
93
- next unless result [ :included ]
94
-
95
- included |= result [ :included ]
101
+ def process_resource ( serializer , include_tree , is_primary , hashes )
102
+ if serializer . respond_to? ( :each )
103
+ serializer . each { |s | process_resource ( s , include_tree , is_primary , hashes ) }
104
+ return
96
105
end
97
-
98
- included . delete_if { |resource | hash [ :data ] . include? ( resource ) }
99
- hash [ :included ] = included if included . any?
100
-
101
- if serializer . paginated?
102
- hash [ :links ] ||= { }
103
- hash [ :links ] . update ( links_for ( serializer , options ) )
106
+ return unless serializer && serializer . object
107
+ resource_identifier = resource_identifier_for ( serializer )
108
+ key = [ resource_identifier_type_for ( serializer ) , resource_identifier_id_for ( serializer ) ]
109
+ if hashes [ key ]
110
+ hashes [ key ] [ :is_primary ] ||= is_primary
111
+ return
104
112
end
105
113
106
- hash
107
- end
114
+ hash = resource_identifier . merge ( is_primary : is_primary )
115
+
116
+ attributes = attributes_for ( serializer )
117
+ hash [ :attributes ] = attributes if attributes . any?
108
118
109
- def serializable_hash_for_single_resource
110
- primary_data = primary_data_for ( serializer )
111
119
relationships = relationships_for ( serializer )
112
- primary_data [ :relationships ] = relationships if relationships . any?
113
- hash = { data : primary_data }
120
+ hash [ :relationships ] = relationships if relationships . any?
114
121
115
- included = included_resources ( @include_tree , [ primary_data ] )
116
- hash [ :included ] = included if included . any?
122
+ hashes [ key ] = hash
117
123
118
- hash
124
+ serializer . associations ( include_tree ) . each do |association |
125
+ process_resource ( association . serializer , include_tree [ association . key ] , false , hashes )
126
+ end
119
127
end
120
128
121
129
def resource_identifier_type_for ( serializer )
@@ -142,26 +150,15 @@ def resource_identifier_for(serializer)
142
150
{ id : id . to_s , type : type }
143
151
end
144
152
145
- def resource_object_for ( serializer )
146
- cache_check ( serializer ) do
147
- resource_object = resource_identifier_for ( serializer )
148
- requested_fields = fieldset && fieldset . fields_for ( resource_object [ :type ] )
149
- attributes = serializer . attributes . except ( :id )
150
- attributes . slice! ( *requested_fields ) if requested_fields
151
- resource_object [ :attributes ] = attributes if attributes . any?
152
- resource_object
153
- end
154
- end
153
+ def attributes_for ( serializer )
154
+ attributes = serializer . attributes . except ( :id )
155
+ requested_fields = fieldset && fieldset . fields_for ( resource_identifier_type_for ( serializer ) )
156
+ attributes . slice! ( *requested_fields ) if requested_fields
155
157
156
- def primary_data_for ( serializer )
157
- if serializer . respond_to? ( :each )
158
- serializer . map { |s | resource_object_for ( s ) }
159
- else
160
- resource_object_for ( serializer )
161
- end
158
+ attributes
162
159
end
163
160
164
- def relationship_value_for ( serializer , options = { } )
161
+ def linkage_for ( serializer , options = { } )
165
162
if serializer . respond_to? ( :each )
166
163
serializer . map { |s | resource_identifier_for ( s ) }
167
164
else
@@ -175,36 +172,7 @@ def relationship_value_for(serializer, options = {})
175
172
176
173
def relationships_for ( serializer )
177
174
serializer . associations . each_with_object ( { } ) do |association , hash |
178
- hash [ association . key ] = { data : relationship_value_for ( association . serializer , association . options ) }
179
- end
180
- end
181
-
182
- def included_resources ( include_tree , primary_data )
183
- included = [ ]
184
-
185
- serializer . associations ( include_tree ) . each do |association |
186
- add_included_resources_for ( association . serializer , include_tree [ association . key ] , primary_data , included )
187
- end
188
-
189
- included
190
- end
191
-
192
- def add_included_resources_for ( serializer , include_tree , primary_data , included )
193
- if serializer . respond_to? ( :each )
194
- serializer . each { |s | add_included_resources_for ( s , include_tree , primary_data , included ) }
195
- else
196
- return unless serializer && serializer . object
197
-
198
- resource_object = primary_data_for ( serializer )
199
- relationships = relationships_for ( serializer )
200
- resource_object [ :relationships ] = relationships if relationships . any?
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
175
+ hash [ association . key ] = { data : linkage_for ( association . serializer , association . options ) }
208
176
end
209
177
end
210
178
0 commit comments