@@ -47,6 +47,11 @@ defmodule JSONAPI.View do
4747 2-arity function inside the view that takes `data` and `conn` as arguments and has
4848 the same name as the field it will be producing. Refer to our `fullname/2` example below.
4949
50+ For historical reasons, the `View` module's "fields" are actually exclusively
51+ attributes. That is, although JSON:API defines fields to be both attributes
52+ and relationships, you should read the `View` module's macros as `field` ->
53+ `attribute` and `relationship` -> `relationship`.
54+
5055 defmodule UserView do
5156 use JSONAPI.View
5257
@@ -233,6 +238,7 @@ defmodule JSONAPI.View do
233238 @ callback path ( ) :: String . t ( ) | nil
234239 @ callback relationships ( ) :: resource_relationships ( )
235240 @ callback polymorphic_relationships ( data ( ) ) :: resource_relationships ( )
241+ @ callback visible_relationships ( data ( ) , Conn . t ( ) | nil ) :: resource_relationships ( )
236242 @ callback type ( ) :: resource_type ( ) | nil
237243 @ callback polymorphic_type ( data ( ) ) :: resource_type ( ) | nil
238244 @ callback url_for ( data ( ) , Conn . t ( ) | nil ) :: String . t ( )
@@ -377,6 +383,10 @@ defmodule JSONAPI.View do
377383 def visible_fields ( data , conn ) ,
378384 do: View . visible_fields ( __MODULE__ , data , conn )
379385
386+ @ impl View
387+ def visible_relationships ( data , conn ) ,
388+ do: View . visible_relationships ( __MODULE__ , data , conn )
389+
380390 def resource_fields ( data ) do
381391 if @ polymorphic_resource? do
382392 polymorphic_fields ( data )
@@ -401,6 +411,24 @@ defmodule JSONAPI.View do
401411 end
402412 end
403413
414+ @ doc """
415+ Get valid attribute and relationship names (collectively known in
416+ JSON:API as "fields", but the name "fields" is taken and left intact for
417+ backwards compatibility).
418+
419+ This function can be used before knowing the data being serialized and as
420+ a consequence it cannot perform polymorphic logic; this is the only way
421+ to operate from the QueryParser Plug.
422+ """
423+ @ spec valid_attrs_and_rels ( ) :: [ atom ( ) ]
424+ def valid_attrs_and_rels ( ) do
425+ if @ polymorphic_resource? do
426+ [ ]
427+ else
428+ fields ( ) ++ Enum . map ( relationships ( ) , fn { name , _ } -> name end )
429+ end
430+ end
431+
404432 defoverridable View
405433
406434 def index ( models , conn , _params , meta \\ nil , options \\ [ ] ) ,
@@ -537,6 +565,23 @@ defmodule JSONAPI.View do
537565 all_fields -- hidden_fields
538566 end
539567
568+ @ spec visible_relationships ( t ( ) , data ( ) , Conn . t ( ) | nil ) :: resource_relationships ( )
569+ def visible_relationships ( view , data , conn ) do
570+ view
571+ |> requested_fields_for_type ( data , conn )
572+ |> net_relationships_for_type ( view . resource_relationships ( data ) )
573+ end
574+
575+ defp net_relationships_for_type ( requested_fields , relationships ) when requested_fields in [ nil , % { } ] ,
576+ do: relationships
577+
578+ defp net_relationships_for_type ( requested_fields , relationships ) do
579+ relationships
580+ |> Enum . filter ( fn { name , _ } ->
581+ Enum . any? ( requested_fields , & Kernel . == ( & 1 , name ) )
582+ end )
583+ end
584+
540585 defp net_fields_for_type ( requested_fields , fields ) when requested_fields in [ nil , % { } ] ,
541586 do: fields
542587
0 commit comments