@@ -98,6 +98,22 @@ def self.get_serializer_for(klass)
9898 end
9999 end
100100
101+ # @api private
102+ def self . include_directive_from_options ( options )
103+ if options [ :include_directive ]
104+ options [ :include_directive ]
105+ elsif options [ :include ]
106+ JSONAPI ::IncludeDirective . new ( options [ :include ] , allow_wildcard : true )
107+ else
108+ ActiveModelSerializers . default_include_directive
109+ end
110+ end
111+
112+ # @api private
113+ def self . serialization_adapter_instance
114+ @serialization_adapter_instance ||= ActiveModelSerializers ::Adapter ::Attributes
115+ end
116+
101117 attr_accessor :object , :root , :scope
102118
103119 # `scope_name` is set as :current_user by default in the controller.
@@ -123,9 +139,7 @@ def success?
123139 # associations, similar to how ActiveModel::Serializers::JSON is used
124140 # in ActiveRecord::Base.
125141 #
126- # TODO: Move to here the Attributes adapter logic for
127- # +serializable_hash_for_single_resource(options)+
128- # and include <tt>ActiveModel::Serializers::JSON</tt>.
142+ # TODO: Include <tt>ActiveModel::Serializers::JSON</tt>.
129143 # So that the below is true:
130144 # @param options [nil, Hash] The same valid options passed to `serializable_hash`
131145 # (:only, :except, :methods, and :include).
@@ -149,11 +163,13 @@ def success?
149163 # serializer.as_json(include: :posts)
150164 # # Second level and higher order associations work as well:
151165 # serializer.as_json(include: { posts: { include: { comments: { only: :body } }, only: :title } })
152- def serializable_hash ( adapter_opts = nil )
153- adapter_opts ||= { }
154- adapter_opts = { include : '*' , adapter : :attributes } . merge! ( adapter_opts )
155- adapter = ActiveModelSerializers ::Adapter . create ( self , adapter_opts )
156- adapter . serializable_hash ( adapter_opts )
166+ def serializable_hash ( adapter_options = nil , options = { } , adapter_instance = self . class . serialization_adapter_instance )
167+ adapter_options ||= { }
168+ options [ :include_directive ] ||= ActiveModel ::Serializer . include_directive_from_options ( adapter_options )
169+ cached_attributes = adapter_options [ :cached_attributes ] ||= { }
170+ resource = cached_attributes ( options [ :fields ] , cached_attributes , adapter_instance )
171+ relationships = resource_relationships ( adapter_options , options , adapter_instance )
172+ resource . merge ( relationships )
157173 end
158174 alias to_hash serializable_hash
159175 alias to_h serializable_hash
@@ -185,6 +201,35 @@ def read_attribute_for_serialization(attr)
185201 end
186202 end
187203
204+ # @api private
205+ def resource_relationships ( adapter_options , options , adapter_instance )
206+ relationships = { }
207+ include_directive = options . fetch ( :include_directive )
208+ associations ( include_directive ) . each do |association |
209+ adapter_opts = adapter_options . merge ( include_directive : include_directive [ association . key ] )
210+ relationships [ association . key ] ||= relationship_value_for ( association , adapter_opts , adapter_instance )
211+ end
212+
213+ relationships
214+ end
215+
216+ # @api private
217+ def relationship_value_for ( association , adapter_options , adapter_instance )
218+ return association . options [ :virtual_value ] if association . options [ :virtual_value ]
219+ association_serializer = association . serializer
220+ association_object = association_serializer && association_serializer . object
221+ return unless association_object
222+
223+ relationship_value = association_serializer . serializable_hash ( adapter_options , { } , adapter_instance )
224+
225+ if association . options [ :polymorphic ] && relationship_value
226+ polymorphic_type = association_object . class . name . underscore
227+ relationship_value = { type : polymorphic_type , polymorphic_type . to_sym => relationship_value }
228+ end
229+
230+ relationship_value
231+ end
232+
188233 protected
189234
190235 attr_accessor :instance_options
0 commit comments