Skip to content

Commit

Permalink
fix: ManyToManys with Pivot Fields should use the child key when the …
Browse files Browse the repository at this point in the history
…model is the pivot schema, not the child schema
  • Loading branch information
staylorwr committed Nov 11, 2021
1 parent 75de0fc commit 6dc6aec
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 8 deletions.
11 changes: 7 additions & 4 deletions lib/ex_teal/fields/many_to_many_belongs_to.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ defmodule ExTeal.Fields.ManyToManyBelongsTo do

def apply_options_for(field, model, _conn, _type) do
queried = field.private_options.queried_resource

rel = queried.model().__schema__(:association, field.field)
is_pivot = model.__struct__ == rel.join_through
[_, referenced_foreign_key] = Keyword.keys(rel.join_keys)

Map.put(field, :options, %{
opts = %{
belongs_to_key: rel.owner_key,
belongs_to_relationship: field.relationship.uri(),
belongs_to_id: model.id
})
belongs_to_id: if(is_pivot, do: Map.get(model, referenced_foreign_key), else: model.id)
}

%{field | options: Map.merge(field.options, opts)}
end
end
3 changes: 1 addition & 2 deletions lib/ex_teal/resource/fields.ex
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ defmodule ExTeal.Resource.Fields do
@doc """
Instead of returning the fields for an index table of a resource,
this function is called to render a simple belongs to field via a
`ManyToManyBelongsTo` field. Eventually this function will look up pivot
fields and return them as well.
`ManyToManyBelongsTo` field.
Given a many to many relationship between posts and tags, an index query
for the tags associated with a post should return a single many to many belongs to
Expand Down
38 changes: 38 additions & 0 deletions test/ex_teal/fields/many_to_many_belongs_to_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
defmodule ExTeal.Fields.ManyToManyBelongsToTest do
use TestExTeal.ConnCase

alias ExTeal.Fields.ManyToManyBelongsTo

describe "apply_options_for/4" do
test "adds belongs to info for pivot relationships", %{conn: conn} do
user = insert(:user)
[_t1, t2] = insert_pair(:tag)
t = insert(:preferred_tag, tag: t2, user: user)

field =
ManyToManyBelongsTo.make(
:preferred_tags,
TestExTeal.TagResource,
TestExTeal.UserResource
)
|> ManyToManyBelongsTo.apply_options_for(t, conn, :index)

assert field.options.belongs_to_id == t2.id
end

test "adds belongs_to info for non-pivot relationships", %{conn: conn} do
[_t1, t2] = insert_pair(:tag)
insert(:post, tags: [t2])

field =
ManyToManyBelongsTo.make(
:tags,
TestExTeal.TagResource,
TestExTeal.PostResource
)
|> ManyToManyBelongsTo.apply_options_for(t2, conn, :index)

assert field.options.belongs_to_id == t2.id
end
end
end
5 changes: 3 additions & 2 deletions test/ex_teal/resource/fields_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ defmodule ExTeal.Resource.FieldsTest do
[t1, t2] = insert_pair(:tag)
u = insert(:user)

insert(:preferred_tag, user: u, tag: t1, order: 2, notes: "foo")
insert(:preferred_tag, user: u, tag: t2, order: 1, notes: "bar")
insert(:preferred_tag)
insert(:preferred_tag, user: u, tag: t2, order: 2, notes: "foo")
insert(:preferred_tag, user: u, tag: t1, order: 1, notes: "bar")

conn =
prep_conn(:get, "tags", %{
Expand Down
1 change: 1 addition & 0 deletions test/ex_teal/resource/index_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ defmodule ExTeal.Resource.IndexTest do
[t1, t2] = insert_pair(:tag)
u = insert(:user)

insert(:preferred_tag)
insert(:preferred_tag, user: u, tag: t2, order: 5, notes: "bar")
insert(:preferred_tag, user: u, tag: t1, order: 2, notes: "foo")

Expand Down

0 comments on commit 6dc6aec

Please sign in to comment.