mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
adding some tests, working on relationship stateful changes
This commit is contained in:
parent
fc259c9012
commit
4e2e013f96
6 changed files with 154 additions and 52 deletions
|
@ -90,7 +90,7 @@ defmodule Ash.Api.Interface do
|
||||||
end
|
end
|
||||||
|
|
||||||
:error ->
|
:error ->
|
||||||
{:error, "no such resource"}
|
{:error, "no such resource #{resource}"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ defmodule Ash.Api.Interface do
|
||||||
end
|
end
|
||||||
|
|
||||||
:error ->
|
:error ->
|
||||||
{:error, "no such resource"}
|
{:error, "no such resource #{resource}"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ defmodule Ash.Api.Interface do
|
||||||
end
|
end
|
||||||
|
|
||||||
:error ->
|
:error ->
|
||||||
{:error, "no such resource"}
|
{:error, "no such resource #{resource}"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ defmodule Ash.Api.Interface do
|
||||||
end
|
end
|
||||||
|
|
||||||
:error ->
|
:error ->
|
||||||
{:error, "no such resource"}
|
{:error, "no such resource #{resource}"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ defmodule Ash.DataLayer.Ets do
|
||||||
|> Enum.reduce({:ok, []}, fn query, {:ok, records} ->
|
|> Enum.reduce({:ok, []}, fn query, {:ok, records} ->
|
||||||
case do_run_query(resource, query, limit + offset) do
|
case do_run_query(resource, query, limit + offset) do
|
||||||
{:ok, results} -> {:ok, records ++ results}
|
{:ok, results} -> {:ok, records ++ results}
|
||||||
{:error, error} -> {:eror, error}
|
{:error, error} -> {:error, error}
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ defmodule Ash.DataLayer.Ets do
|
||||||
{:ok, match_spec} <- filter_to_matchspec(resource, filter),
|
{:ok, match_spec} <- filter_to_matchspec(resource, filter),
|
||||||
{:ok, table} <- wrap_or_create_table(resource),
|
{:ok, table} <- wrap_or_create_table(resource),
|
||||||
{:ok, results} <- match_limit(table, match_spec, limit) do
|
{:ok, results} <- match_limit(table, match_spec, limit) do
|
||||||
{:ok, results}
|
{:ok, Enum.map(results, &elem(&1, 1))}
|
||||||
else
|
else
|
||||||
%{errors: errors} ->
|
%{errors: errors} ->
|
||||||
{:error, errors}
|
{:error, errors}
|
||||||
|
|
|
@ -45,10 +45,7 @@ defmodule Ash.Filter.Merge do
|
||||||
# end
|
# end
|
||||||
|
|
||||||
defp do_merge(left, right) do
|
defp do_merge(left, right) do
|
||||||
# There is no way this can reasonably fail
|
And.prebuilt_new(left, right)
|
||||||
{:ok, predicate} = And.prebuilt_new(left, right)
|
|
||||||
|
|
||||||
predicate
|
|
||||||
end
|
end
|
||||||
|
|
||||||
## Equals + In filters
|
## Equals + In filters
|
||||||
|
|
|
@ -19,6 +19,8 @@ defmodule Ash.Type do
|
||||||
|
|
||||||
@builtins [
|
@builtins [
|
||||||
string: [ecto_type: :string, filters: [:equal, :in], sortable?: true],
|
string: [ecto_type: :string, filters: [:equal, :in], sortable?: true],
|
||||||
|
integer: [ecto_type: :integer, filters: [:equal, :in], sortable?: true],
|
||||||
|
int: [ecto_type: :integer, filters: [:equal, :in], sortable?: true],
|
||||||
boolean: [ecto_type: :boolean, filters: [:equal], sortable?: true],
|
boolean: [ecto_type: :boolean, filters: [:equal], sortable?: true],
|
||||||
uuid: [ecto_type: :binary_id, filters: [:equal, :in], sortable?: true],
|
uuid: [ecto_type: :binary_id, filters: [:equal, :in], sortable?: true],
|
||||||
utc_datetime: [ecto_type: :utc_datetime, filters: [:equal, :in], sortable?: true]
|
utc_datetime: [ecto_type: :utc_datetime, filters: [:equal, :in], sortable?: true]
|
||||||
|
|
|
@ -45,36 +45,28 @@ defmodule Ash.Test.Actions.SideLoadTest do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "side_loads" do
|
describe "side_loads" do
|
||||||
# setup do
|
setup do
|
||||||
# author = Api.create!(Author, attributes: %{name: "zerg"})
|
author = Api.create!(Author, attributes: %{name: "zerg"})
|
||||||
|
|
||||||
# post1 =
|
post1 =
|
||||||
# Api.create!(Post, attributes: %{title: "post1"}, relationships: %{author: author.id})
|
Api.create!(Post, attributes: %{title: "post1"}, relationships: %{author: author.id})
|
||||||
|
|
||||||
# post2 =
|
post2 =
|
||||||
# Api.create!(Post, attributes: %{title: "post2"}, relationships: %{author: author.id})
|
Api.create!(Post, attributes: %{title: "post2"}, relationships: %{author: author.id})
|
||||||
|
|
||||||
# %{post1: post1, post2: post2}
|
%{post1: post1, post2: post2}
|
||||||
# end
|
|
||||||
|
|
||||||
test "mything" do
|
|
||||||
Api.read!(Author, filter: [or: [[name: "zach"], [posts: [id: Ecto.UUID.generate()]]]])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# test "it allows sideloading related data", %{post1: post1, post2: post2} do
|
test "it allows sideloading related data", %{post1: post1, post2: post2} do
|
||||||
# %{results: [author]} =
|
%{results: [author]} =
|
||||||
# Api.read!(Author, side_load: [posts: [:author]], filter: [posts: [id: post1.id]])
|
Api.read!(Author, side_load: [posts: [:author]], filter: [posts: [id: post1.id]])
|
||||||
|
|
||||||
# Api.read!(Author,
|
assert Enum.sort(Enum.map(author.posts, &Map.get(&1, :id))) ==
|
||||||
# filter: [name: "zach", posts: [id: post1.id, title: "foo", contents: "bar"]]
|
Enum.sort([post1.id, post2.id])
|
||||||
# )
|
|
||||||
|
|
||||||
# assert Enum.sort(Enum.map(author.posts, &Map.get(&1, :id))) ==
|
for post <- author.posts do
|
||||||
# Enum.sort([post1.id, post2.id])
|
assert post.author.id == author.id
|
||||||
|
end
|
||||||
# for post <- author.posts do
|
end
|
||||||
# assert post.author.id == author.id
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,27 @@
|
||||||
defmodule Ash.Test.Filter.FilterTest do
|
defmodule Ash.Test.Filter.FilterTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
defmodule Profile do
|
||||||
|
use Ash.Resource, name: "profiles", type: "profile"
|
||||||
|
use Ash.DataLayer.Ets, private?: true
|
||||||
|
|
||||||
|
actions do
|
||||||
|
read :default
|
||||||
|
create :default
|
||||||
|
update :default
|
||||||
|
end
|
||||||
|
|
||||||
|
attributes do
|
||||||
|
attribute :bio, :string
|
||||||
|
end
|
||||||
|
|
||||||
|
relationships do
|
||||||
|
belongs_to :user, Ash.Test.Filter.FilterTest.User,
|
||||||
|
source_field: :user_id,
|
||||||
|
destination_field: :id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defmodule User do
|
defmodule User do
|
||||||
use Ash.Resource, name: "users", type: "user"
|
use Ash.Resource, name: "users", type: "user"
|
||||||
use Ash.DataLayer.Ets, private?: true
|
use Ash.DataLayer.Ets, private?: true
|
||||||
|
@ -8,6 +29,7 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
actions do
|
actions do
|
||||||
read :default
|
read :default
|
||||||
create :default
|
create :default
|
||||||
|
update :default
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
|
@ -17,6 +39,27 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
has_many :posts, Ash.Test.Filter.FilterTest.Post
|
has_many :posts, Ash.Test.Filter.FilterTest.Post
|
||||||
|
|
||||||
|
has_one :profile, Profile,
|
||||||
|
destination_field: :user_id,
|
||||||
|
source_field: :id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule PostLink do
|
||||||
|
use Ash.Resource, name: "post_links", type: "post_link", primary_key: false
|
||||||
|
use Ash.DataLayer.Ets, private?: true
|
||||||
|
|
||||||
|
actions do
|
||||||
|
read :default
|
||||||
|
|
||||||
|
create :default
|
||||||
|
update :default
|
||||||
|
end
|
||||||
|
|
||||||
|
relationships do
|
||||||
|
belongs_to :source_post, Ash.Test.Filter.FilterTest.Post, primary_key?: true
|
||||||
|
belongs_to :destination_post, Ash.Test.Filter.FilterTest.Post, primary_key?: true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -28,11 +71,14 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
read :default
|
read :default
|
||||||
|
|
||||||
create :default
|
create :default
|
||||||
|
|
||||||
|
update :default
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
attribute :title, :string
|
attribute :title, :string
|
||||||
attribute :contents, :string
|
attribute :contents, :string
|
||||||
|
attribute :points, :integer
|
||||||
end
|
end
|
||||||
|
|
||||||
relationships do
|
relationships do
|
||||||
|
@ -43,33 +89,98 @@ defmodule Ash.Test.Filter.FilterTest do
|
||||||
belongs_to :author2, User,
|
belongs_to :author2, User,
|
||||||
destination_field: :id,
|
destination_field: :id,
|
||||||
source_field: :author2_id
|
source_field: :author2_id
|
||||||
|
|
||||||
|
many_to_many :related_posts, __MODULE__,
|
||||||
|
through: PostLink,
|
||||||
|
source_field_on_join_table: :source_post_id,
|
||||||
|
destination_field_on_join_table: :destination_post_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defmodule Api do
|
defmodule Api do
|
||||||
use Ash.Api
|
use Ash.Api
|
||||||
|
|
||||||
resources [Post, Author]
|
resources [Post, User, Profile]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it works" do
|
describe "simple attribute filters" do
|
||||||
authorization_steps = [
|
setup do
|
||||||
authorize_if: [author1: [id: 1]],
|
post1 = Api.create!(Post, attributes: %{title: "title1", contents: "contents1", points: 1})
|
||||||
forbid_if: [author1: [allow_second_author: false]],
|
post2 = Api.create!(Post, attributes: %{title: "title2", contents: "contents2", points: 2})
|
||||||
authorize_if: [author2: [id: 1]]
|
|
||||||
]
|
|
||||||
|
|
||||||
Ash.Filter.SatSolver.solve(Post, authorization_steps)
|
%{post1: post1, post2: post2}
|
||||||
|
end
|
||||||
|
|
||||||
# Api.read(Post,
|
test "single filter field", %{post1: post1} do
|
||||||
# filter: [
|
assert %{results: [^post1]} =
|
||||||
# title: "foo",
|
Api.read!(Post,
|
||||||
# title: "bar",
|
filter: [
|
||||||
# contents: [in: ["bar", "baz"]],
|
title: post1.title
|
||||||
# contents: [in: ["foo", "bar"]],
|
]
|
||||||
# author1: [id: 1],
|
)
|
||||||
# author2: [name: "bob"]
|
end
|
||||||
# ]
|
|
||||||
# )
|
test "multiple filter field matches", %{post1: post1} do
|
||||||
|
assert %{results: [^post1]} =
|
||||||
|
Api.read!(Post,
|
||||||
|
filter: [
|
||||||
|
title: post1.title,
|
||||||
|
contents: post1.contents
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "no field matches" do
|
||||||
|
assert %{results: []} =
|
||||||
|
Api.read!(Post,
|
||||||
|
filter: [
|
||||||
|
title: "no match"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "no field matches single record, but each matches one record", %{
|
||||||
|
post1: post1,
|
||||||
|
post2: post2
|
||||||
|
} do
|
||||||
|
assert %{results: []} =
|
||||||
|
Api.read!(Post,
|
||||||
|
filter: [
|
||||||
|
title: post1.title,
|
||||||
|
contents: post2.contents
|
||||||
|
]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "relationship filters" do
|
||||||
|
setup do
|
||||||
|
post1 = Api.create!(Post, attributes: %{title: "title1", contents: "contents1", points: 1})
|
||||||
|
post2 = Api.create!(Post, attributes: %{title: "title2", contents: "contents2", points: 2})
|
||||||
|
|
||||||
|
# post3 =
|
||||||
|
# Api.create!(Post,
|
||||||
|
# attributes: %{title: "title3", contents: "contents3", points: 3},
|
||||||
|
# relationships: %{related_posts: [post1, post2]}
|
||||||
|
# )
|
||||||
|
|
||||||
|
profile1 = Api.create!(Profile, attributes: %{bio: "dope"})
|
||||||
|
|
||||||
|
user1 =
|
||||||
|
Api.create!(User,
|
||||||
|
attributes: %{name: "broseph"},
|
||||||
|
relationships: %{posts: [post1, post2], profile: profile1}
|
||||||
|
)
|
||||||
|
|
||||||
|
user2 = Api.create!(User, attributes: %{name: "broseph"}, relationships: %{posts: [post2]})
|
||||||
|
|
||||||
|
profile2 = Api.create!(Profile, attributes: %{bio: "dope2"}, relationships: %{user: user2})
|
||||||
|
|
||||||
|
%{post1: post1, post2: post2}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "it works" do
|
||||||
|
assert true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue