mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
finishing up action tests
This commit is contained in:
parent
06e372e029
commit
6702c8eb3a
5 changed files with 89 additions and 29 deletions
|
@ -122,3 +122,6 @@ end
|
||||||
* Clean up and test filter inspecting code.
|
* Clean up and test filter inspecting code.
|
||||||
* Handle related values on delete
|
* Handle related values on delete
|
||||||
* Use ashton to validate interface opts, not just document them: Easy and important
|
* Use ashton to validate interface opts, not just document them: Easy and important
|
||||||
|
* Make an automatic test suite that confirms that data layers behave the way
|
||||||
|
they claim to behave, maybe.
|
||||||
|
* Perhaps, reverse relationships should eliminate the need to set destination field.
|
||||||
|
|
|
@ -191,21 +191,25 @@ defmodule Ash.Actions.ChangesetHelpers do
|
||||||
defp many_to_many_assoc_update(changeset, rel, filters, authorize?, user) do
|
defp many_to_many_assoc_update(changeset, rel, filters, authorize?, user) do
|
||||||
changeset
|
changeset
|
||||||
|> before_change(fn %{__ash_api__: api} = changeset ->
|
|> before_change(fn %{__ash_api__: api} = changeset ->
|
||||||
source_field_value = Ecto.Changeset.get_field(changeset, rel.source_field)
|
if changeset.action == :update do
|
||||||
|
source_field_value = Ecto.Changeset.get_field(changeset, rel.source_field)
|
||||||
|
|
||||||
destroy_result =
|
destroy_result =
|
||||||
destroy_no_longer_related_join_table_rows(
|
destroy_no_longer_related_join_table_rows(
|
||||||
api,
|
api,
|
||||||
source_field_value,
|
source_field_value,
|
||||||
rel,
|
rel,
|
||||||
filters,
|
filters,
|
||||||
authorize?,
|
authorize?,
|
||||||
user
|
user
|
||||||
)
|
)
|
||||||
|
|
||||||
case destroy_result do
|
case destroy_result do
|
||||||
:ok -> changeset
|
:ok -> changeset
|
||||||
{:error, error} -> {:error, error}
|
{:error, error} -> {:error, error}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
changeset
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|> after_change(fn %{__ash_api__: api}, result ->
|
|> after_change(fn %{__ash_api__: api}, result ->
|
||||||
|
|
|
@ -168,6 +168,24 @@ defmodule Ash.Api.Interface do
|
||||||
@callback destroy(record :: Ash.record(), params :: Ash.update_params()) ::
|
@callback destroy(record :: Ash.record(), params :: Ash.update_params()) ::
|
||||||
{:ok, Ash.record()} | {:error, Ash.error()}
|
{:ok, Ash.record()} | {:error, Ash.error()}
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Refetches a record from the database
|
||||||
|
"""
|
||||||
|
@callback reload(record :: Ash.record(), params :: Ash.params()) ::
|
||||||
|
{:ok, Ash.record()} | {:error, Ash.error()}
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Refetches a record from the database, raising on error.
|
||||||
|
|
||||||
|
See `reload/1`.
|
||||||
|
"""
|
||||||
|
@callback reload!(record :: Ash.record(), params :: Ash.params()) :: Ash.record() | no_return
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Refetches a record from the database
|
||||||
|
"""
|
||||||
|
@callback reload(record :: Ash.record()) :: {:ok, Ash.record()} | {:error, Ash.error()}
|
||||||
|
|
||||||
defmacro __using__(_) do
|
defmacro __using__(_) do
|
||||||
quote do
|
quote do
|
||||||
@behaviour Ash.Api.Interface
|
@behaviour Ash.Api.Interface
|
||||||
|
@ -236,6 +254,18 @@ defmodule Ash.Api.Interface do
|
||||||
{:error, error} -> {:error, List.wrap(error)}
|
{:error, error} -> {:error, List.wrap(error)}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def reload!(%resource{} = record, params \\ []) do
|
||||||
|
id = record |> Map.take(Ash.primary_key(resource)) |> Enum.to_list()
|
||||||
|
get!(resource, id, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def reload(%resource{} = record, params \\ []) do
|
||||||
|
id = record |> Map.take(Ash.primary_key(resource)) |> Enum.to_list()
|
||||||
|
get(resource, id, params)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -191,7 +191,7 @@ defmodule Ash.DataLayer.Ets do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp related_ids_filter(%{cardinality: :many_to_many} = rel, filter) do
|
defp related_ids_filter(%{type: :many_to_many} = rel, filter) do
|
||||||
destination_query = %Query{
|
destination_query = %Query{
|
||||||
resource: rel.destination,
|
resource: rel.destination,
|
||||||
filter: filter
|
filter: filter
|
||||||
|
|
|
@ -16,9 +16,7 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
belongs_to :user, Ash.Test.Filter.FilterTest.User,
|
belongs_to :user, Ash.Test.Filter.FilterTest.User
|
||||||
source_field: :user_id,
|
|
||||||
destination_field: :id
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -38,11 +36,15 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
has_many :posts, Ash.Test.Filter.FilterTest.Post, reverse_relationship: :author1
|
has_many :posts, Ash.Test.Filter.FilterTest.Post,
|
||||||
|
reverse_relationship: :author1,
|
||||||
|
destination_field: :author1_id
|
||||||
|
|
||||||
has_one :profile, Profile,
|
has_many :second_posts, Ash.Test.Filter.FilterTest.Post,
|
||||||
destination_field: :user_id,
|
reverse_relationship: :author2,
|
||||||
source_field: :id
|
destination_field: :author1_id
|
||||||
|
|
||||||
|
has_one :profile, Profile
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -165,6 +167,12 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
relationships: %{related_posts: [post1, post2]}
|
relationships: %{related_posts: [post1, post2]}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
post4 =
|
||||||
|
Api.create!(Post,
|
||||||
|
attributes: %{title: "title4", contents: "contents3", points: 4},
|
||||||
|
relationships: %{related_posts: [post3]}
|
||||||
|
)
|
||||||
|
|
||||||
profile1 = Api.create!(Profile, attributes: %{bio: "dope"})
|
profile1 = Api.create!(Profile, attributes: %{bio: "dope"})
|
||||||
|
|
||||||
user1 =
|
user1 =
|
||||||
|
@ -178,16 +186,31 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
profile2 = Api.create!(Profile, attributes: %{bio: "dope2"}, relationships: %{user: user2})
|
profile2 = Api.create!(Profile, attributes: %{bio: "dope2"}, relationships: %{user: user2})
|
||||||
|
|
||||||
%{
|
%{
|
||||||
post1: post1,
|
post1: Api.reload!(post1),
|
||||||
post2: post2,
|
post2: Api.reload!(post2),
|
||||||
post3: post3,
|
post3: Api.reload!(post3),
|
||||||
profile1: profile1,
|
post4: Api.reload!(post4),
|
||||||
user1: user1,
|
profile1: Api.reload!(profile1),
|
||||||
user2: user2,
|
user1: Api.reload!(user1),
|
||||||
profile2: profile2
|
user2: Api.reload!(user2),
|
||||||
|
profile2: Api.reload!(profile2)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it works"
|
test "filtering on a has_one relationship", %{profile2: profile2, user2: user2} do
|
||||||
|
assert %{results: [^user2]} = Api.read!(User, filter: [profile: profile2.id])
|
||||||
|
end
|
||||||
|
|
||||||
|
test "filtering on a belongs_to relationship", %{profile1: profile1, user1: user1} do
|
||||||
|
assert %{results: [^profile1]} = Api.read!(Profile, filter: [user: user1.id])
|
||||||
|
end
|
||||||
|
|
||||||
|
test "filtering on a has_many relationship", %{user2: user2, post2: post2} do
|
||||||
|
assert %{results: [^user2]} = Api.read!(User, filter: [posts: post2.id])
|
||||||
|
end
|
||||||
|
|
||||||
|
test "filtering on a many_to_many relationship", %{post4: post4, post3: post3} do
|
||||||
|
assert %{results: [^post4]} = Api.read!(Post, filter: [related_posts: post3.id])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue