Skip to content

Commit

Permalink
Fix relationships spec & external relationship use-case (#295)
Browse files Browse the repository at this point in the history
* update spec for relationships callback.

* fix support for external relationships via renaming and add test coverage for it.

* apply mix format
  • Loading branch information
mattpolzin committed Jun 26, 2023
1 parent 1f236ef commit a2728f5
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 4 deletions.
2 changes: 1 addition & 1 deletion lib/jsonapi/serializer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ defmodule JSONAPI.Serializer do
@spec encode_relationships(Conn.t(), document(), tuple(), list()) :: tuple()
def encode_relationships(conn, doc, {view, data, _, _} = view_info, options) do
view.relationships()
|> Enum.filter(&data_loaded?(Map.get(data, get_data_key(&1))))
|> Enum.filter(&assoc_loaded?(Map.get(data, get_data_key(&1))))
|> Enum.map_reduce(doc, &build_relationships(conn, view_info, &1, &2, options))
end

Expand Down
4 changes: 3 additions & 1 deletion lib/jsonapi/view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ defmodule JSONAPI.View do
@callback pagination_links(data(), Conn.t(), Paginator.page(), Paginator.options()) ::
Paginator.links()
@callback path() :: String.t() | nil
@callback relationships() :: [{atom(), t() | {t(), :include}}]
@callback relationships() :: [
{atom(), t() | {t(), :include} | {atom(), t()} | {atom(), t(), :include}}
]
@callback type() :: resource_type()
@callback url_for(data(), Conn.t() | nil) :: String.t()
@callback url_for_pagination(data(), Conn.t(), Paginator.params()) :: String.t()
Expand Down
18 changes: 16 additions & 2 deletions test/jsonapi/serializer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ defmodule JSONAPI.SerializerTest do
end
end

defmodule ExternalUserView do
use JSONAPI.View, type: "euser"

def id(attribute), do: attribute

def fields, do: []
end

defmodule CompanyView do
use JSONAPI.View

Expand Down Expand Up @@ -133,10 +141,12 @@ defmodule JSONAPI.SerializerTest do
# renames "user1" data property to "commenter" JSON:API relationship (and specifies default inclusion)
# renames "user2" to "witness"
# leaves "user3" name alone
# handles "user4" by looking at the "external_user" property (some other service's user)
[
commenter: {:user1, JSONAPI.SerializerTest.UserView, :include},
witness: {:user2, JSONAPI.SerializerTest.UserView},
user3: JSONAPI.SerializerTest.UserView
user3: JSONAPI.SerializerTest.UserView,
user4: {:external_user, JSONAPI.SerializerTest.ExternalUserView}
]
end
end
Expand Down Expand Up @@ -346,6 +356,7 @@ defmodule JSONAPI.SerializerTest do
data = %{
id: 1,
text: "hello world",
external_user: "b29b5bb0-38d6-206a-29dd-a1db3452156b",
user1: %{
id: 2,
username: "hi",
Expand Down Expand Up @@ -379,6 +390,8 @@ defmodule JSONAPI.SerializerTest do
assert encoded.data.relationships.commenter != nil
assert encoded.data.relationships.witness != nil
assert encoded.data.relationships.user3 != nil
assert encoded.data.relationships.user4 != nil
assert encoded.data.relationships.user4.data.id == "b29b5bb0-38d6-206a-29dd-a1db3452156b"
refute Map.has_key?(encoded.data.relationships, :user1)
refute Map.has_key?(encoded.data.relationships, :user2)

Expand Down Expand Up @@ -768,7 +781,8 @@ defmodule JSONAPI.SerializerTest do
assert configs == [
{:commenter, :user1, JSONAPI.SerializerTest.UserView, true},
{:witness, :user2, JSONAPI.SerializerTest.UserView, false},
{:user3, :user3, JSONAPI.SerializerTest.UserView, false}
{:user3, :user3, JSONAPI.SerializerTest.UserView, false},
{:user4, :external_user, JSONAPI.SerializerTest.ExternalUserView, false}
]
end
end

0 comments on commit a2728f5

Please sign in to comment.