@@ -140,10 +140,12 @@ defmodule JSONAPI.View do
140140 @ type options :: keyword ( )
141141 @ type resource_id :: String . t ( )
142142 @ type resource_type :: String . t ( )
143+ @ type polymorphic_resource :: boolean ( )
143144
144145 @ callback attributes ( data ( ) , Conn . t ( ) | nil ) :: map ( )
145146 @ callback id ( data ( ) ) :: resource_id ( ) | nil
146147 @ callback fields ( ) :: [ field ( ) ]
148+ @ callback polymorphic_fields ( data ( ) ) :: [ field ( ) ]
147149 @ callback get_field ( field ( ) , data ( ) , Conn . t ( ) ) :: any ( )
148150 @ callback hidden ( data ( ) ) :: [ field ( ) ]
149151 @ callback links ( data ( ) , Conn . t ( ) ) :: links ( )
@@ -156,6 +158,7 @@ defmodule JSONAPI.View do
156158 { atom ( ) , t ( ) | { t ( ) , :include } | { atom ( ) , t ( ) } | { atom ( ) , t ( ) , :include } }
157159 ]
158160 @ callback type ( ) :: resource_type ( )
161+ @ callback polymorphic_type ( data ( ) ) :: resource_type ( )
159162 @ callback url_for ( data ( ) , Conn . t ( ) | nil ) :: String . t ( )
160163 @ callback url_for_pagination ( data ( ) , Conn . t ( ) , Paginator . params ( ) ) :: String . t ( )
161164 @ callback url_for_rel ( term ( ) , String . t ( ) , Conn . t ( ) | nil ) :: String . t ( )
@@ -167,7 +170,8 @@ defmodule JSONAPI.View do
167170 { type , opts } = Keyword . pop ( opts , :type )
168171 { namespace , opts } = Keyword . pop ( opts , :namespace )
169172 { path , opts } = Keyword . pop ( opts , :path )
170- { paginator , _opts } = Keyword . pop ( opts , :paginator )
173+ { paginator , opts } = Keyword . pop ( opts , :paginator )
174+ { polymorphic_resource , _opts } = Keyword . pop ( opts , :polymorphic_resource , false )
171175
172176 quote do
173177 alias JSONAPI . { Serializer , View }
@@ -178,6 +182,7 @@ defmodule JSONAPI.View do
178182 @ namespace unquote ( namespace )
179183 @ path unquote ( path )
180184 @ paginator unquote ( paginator )
185+ @ polymorphic_resource unquote ( polymorphic_resource )
181186
182187 @ impl View
183188 def id ( nil ) , do: nil
@@ -205,8 +210,21 @@ defmodule JSONAPI.View do
205210 end )
206211 end
207212
208- @ impl View
209- def fields , do: raise ( "Need to implement fields/0" )
213+ cond do
214+ ! @ polymorphic_resource ->
215+ @ impl View
216+ def fields , do: raise ( "Need to implement fields/0" )
217+
218+ @ impl View
219+ def polymorphic_fields ( _data ) , do: nil
220+
221+ @ polymorphic_resource ->
222+ @ impl View
223+ def fields , do: nil
224+
225+ @ impl View
226+ def polymorphic_fields ( _data ) , do: raise ( "Need to implement polymorphic_fields/1" )
227+ end
210228
211229 @ impl View
212230 def hidden ( _data ) , do: [ ]
@@ -241,11 +259,27 @@ defmodule JSONAPI.View do
241259 @ impl View
242260 def relationships , do: [ ]
243261
244- @ impl View
245- if @ resource_type do
246- def type , do: @ resource_type
247- else
248- def type , do: raise ( "Need to implement type/0" )
262+ cond do
263+ @ resource_type ->
264+ @ impl View
265+ def type , do: @ resource_type
266+
267+ @ impl View
268+ def polymorphic_type ( _data ) , do: nil
269+
270+ ! @ polymorphic_resource ->
271+ @ impl View
272+ def type , do: raise ( "Need to implement type/0" )
273+
274+ @ impl View
275+ def polymorphic_type ( _data ) , do: nil
276+
277+ @ polymorphic_resource ->
278+ @ impl View
279+ def type , do: nil
280+
281+ @ impl View
282+ def polymorphic_type ( _data ) , do: raise ( "Need to implement polymorphic_type/1" )
249283 end
250284
251285 @ impl View
@@ -264,6 +298,22 @@ defmodule JSONAPI.View do
264298 def visible_fields ( data , conn ) ,
265299 do: View . visible_fields ( __MODULE__ , data , conn )
266300
301+ def resource_fields ( data ) do
302+ if @ polymorphic_resource do
303+ polymorphic_fields ( data )
304+ else
305+ fields ( )
306+ end
307+ end
308+
309+ def resource_type ( data ) do
310+ if @ polymorphic_resource do
311+ polymorphic_type ( data )
312+ else
313+ type ( )
314+ end
315+ end
316+
267317 defoverridable View
268318
269319 def index ( models , conn , _params , meta \\ nil , options \\ [ ] ) ,
@@ -336,11 +386,11 @@ defmodule JSONAPI.View do
336386
337387 @ spec url_for ( t ( ) , term ( ) , Conn . t ( ) | nil ) :: String . t ( )
338388 def url_for ( view , data , nil = _conn ) when is_nil ( data ) or is_list ( data ) ,
339- do: URI . to_string ( % URI { path: Enum . join ( [ view . namespace ( ) , path_for ( view ) ] , "/" ) } )
389+ do: URI . to_string ( % URI { path: Enum . join ( [ view . namespace ( ) , path_for ( view , data ) ] , "/" ) } )
340390
341391 def url_for ( view , data , nil = _conn ) do
342392 URI . to_string ( % URI {
343- path: Enum . join ( [ view . namespace ( ) , path_for ( view ) , view . id ( data ) ] , "/" )
393+ path: Enum . join ( [ view . namespace ( ) , path_for ( view , data ) , view . id ( data ) ] , "/" )
344394 } )
345395 end
346396
@@ -349,7 +399,7 @@ defmodule JSONAPI.View do
349399 scheme: scheme ( conn ) ,
350400 host: host ( conn ) ,
351401 port: port ( conn ) ,
352- path: Enum . join ( [ view . namespace ( ) , path_for ( view ) ] , "/" )
402+ path: Enum . join ( [ view . namespace ( ) , path_for ( view , data ) ] , "/" )
353403 } )
354404 end
355405
@@ -358,7 +408,7 @@ defmodule JSONAPI.View do
358408 scheme: scheme ( conn ) ,
359409 host: host ( conn ) ,
360410 port: port ( conn ) ,
361- path: Enum . join ( [ view . namespace ( ) , path_for ( view ) , view . id ( data ) ] , "/" )
411+ path: Enum . join ( [ view . namespace ( ) , path_for ( view , data ) , view . id ( data ) ] , "/" )
362412 } )
363413 end
364414
@@ -392,8 +442,8 @@ defmodule JSONAPI.View do
392442 def visible_fields ( view , data , conn ) do
393443 all_fields =
394444 view
395- |> requested_fields_for_type ( conn )
396- |> net_fields_for_type ( view . fields ( ) )
445+ |> requested_fields_for_type ( data , conn )
446+ |> net_fields_for_type ( view . resource_fields ( data ) )
397447
398448 hidden_fields = view . hidden ( data )
399449
@@ -420,11 +470,11 @@ defmodule JSONAPI.View do
420470 |> URI . to_string ( )
421471 end
422472
423- defp requested_fields_for_type ( view , % Conn { assigns: % { jsonapi_query: % { fields: fields } } } ) do
424- fields [ view . type ( ) ]
473+ defp requested_fields_for_type ( view , data , % Conn { assigns: % { jsonapi_query: % { fields: fields } } } ) do
474+ fields [ view . resource_type ( data ) ]
425475 end
426476
427- defp requested_fields_for_type ( _view , _conn ) , do: nil
477+ defp requested_fields_for_type ( _view , _data , _conn ) , do: nil
428478
429479 defp host ( % Conn { host: host } ) ,
430480 do: Application . get_env ( :jsonapi , :host , host )
@@ -438,5 +488,5 @@ defmodule JSONAPI.View do
438488 defp scheme ( % Conn { scheme: scheme } ) ,
439489 do: Application . get_env ( :jsonapi , :scheme , to_string ( scheme ) )
440490
441- defp path_for ( view ) , do: view . path ( ) || view . type ( )
491+ defp path_for ( view , data ) , do: view . path ( ) || view . resource_type ( data )
442492end
0 commit comments