adding some tests, working on relationship stateful changes

This commit is contained in:
Zach Daniel 2019-12-20 00:30:27 -05:00
parent fc259c9012
commit 4e2e013f96
No known key found for this signature in database
GPG key ID: A57053A671EE649E
6 changed files with 154 additions and 52 deletions

View file

@ -90,7 +90,7 @@ defmodule Ash.Api.Interface do
end
:error ->
{:error, "no such resource"}
{:error, "no such resource #{resource}"}
end
end
@ -114,7 +114,7 @@ defmodule Ash.Api.Interface do
end
:error ->
{:error, "no such resource"}
{:error, "no such resource #{resource}"}
end
end
@ -136,7 +136,7 @@ defmodule Ash.Api.Interface do
end
:error ->
{:error, "no such resource"}
{:error, "no such resource #{resource}"}
end
end
@ -158,7 +158,7 @@ defmodule Ash.Api.Interface do
end
:error ->
{:error, "no such resource"}
{:error, "no such resource #{resource}"}
end
end

View file

@ -84,7 +84,7 @@ defmodule Ash.DataLayer.Ets do
|> Enum.reduce({:ok, []}, fn query, {:ok, records} ->
case do_run_query(resource, query, limit + offset) do
{:ok, results} -> {:ok, records ++ results}
{:error, error} -> {:eror, error}
{:error, error} -> {:error, error}
end
end)
@ -109,7 +109,7 @@ defmodule Ash.DataLayer.Ets do
{:ok, match_spec} <- filter_to_matchspec(resource, filter),
{:ok, table} <- wrap_or_create_table(resource),
{:ok, results} <- match_limit(table, match_spec, limit) do
{:ok, results}
{:ok, Enum.map(results, &elem(&1, 1))}
else
%{errors: errors} ->
{:error, errors}

View file

@ -45,10 +45,7 @@ defmodule Ash.Filter.Merge do
# end
defp do_merge(left, right) do
# There is no way this can reasonably fail
{:ok, predicate} = And.prebuilt_new(left, right)
predicate
And.prebuilt_new(left, right)
end
## Equals + In filters

View file

@ -19,6 +19,8 @@ defmodule Ash.Type do
@builtins [
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],
uuid: [ecto_type: :binary_id, filters: [:equal, :in], sortable?: true],
utc_datetime: [ecto_type: :utc_datetime, filters: [:equal, :in], sortable?: true]

View file

@ -45,36 +45,28 @@ defmodule Ash.Test.Actions.SideLoadTest do
end
describe "side_loads" do
# setup do
# author = Api.create!(Author, attributes: %{name: "zerg"})
setup do
author = Api.create!(Author, attributes: %{name: "zerg"})
# post1 =
# Api.create!(Post, attributes: %{title: "post1"}, relationships: %{author: author.id})
post1 =
Api.create!(Post, attributes: %{title: "post1"}, relationships: %{author: author.id})
# post2 =
# Api.create!(Post, attributes: %{title: "post2"}, relationships: %{author: author.id})
post2 =
Api.create!(Post, attributes: %{title: "post2"}, relationships: %{author: author.id})
# %{post1: post1, post2: post2}
# end
test "mything" do
Api.read!(Author, filter: [or: [[name: "zach"], [posts: [id: Ecto.UUID.generate()]]]])
%{post1: post1, post2: post2}
end
# test "it allows sideloading related data", %{post1: post1, post2: post2} do
# %{results: [author]} =
# Api.read!(Author, side_load: [posts: [:author]], filter: [posts: [id: post1.id]])
test "it allows sideloading related data", %{post1: post1, post2: post2} do
%{results: [author]} =
Api.read!(Author, side_load: [posts: [:author]], filter: [posts: [id: post1.id]])
# Api.read!(Author,
# filter: [name: "zach", posts: [id: post1.id, title: "foo", contents: "bar"]]
# )
assert Enum.sort(Enum.map(author.posts, &Map.get(&1, :id))) ==
Enum.sort([post1.id, post2.id])
# assert Enum.sort(Enum.map(author.posts, &Map.get(&1, :id))) ==
# Enum.sort([post1.id, post2.id])
# for post <- author.posts do
# assert post.author.id == author.id
# end
# end
for post <- author.posts do
assert post.author.id == author.id
end
end
end
end

View file

@ -1,6 +1,27 @@
defmodule Ash.Test.Filter.FilterTest do
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
use Ash.Resource, name: "users", type: "user"
use Ash.DataLayer.Ets, private?: true
@ -8,6 +29,7 @@ defmodule Ash.Test.Filter.FilterTest do
actions do
read :default
create :default
update :default
end
attributes do
@ -17,6 +39,27 @@ defmodule Ash.Test.Filter.FilterTest do
relationships do
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
@ -28,11 +71,14 @@ defmodule Ash.Test.Filter.FilterTest do
read :default
create :default
update :default
end
attributes do
attribute :title, :string
attribute :contents, :string
attribute :points, :integer
end
relationships do
@ -43,33 +89,98 @@ defmodule Ash.Test.Filter.FilterTest do
belongs_to :author2, User,
destination_field: :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
defmodule Api do
use Ash.Api
resources [Post, Author]
resources [Post, User, Profile]
end
test "it works" do
authorization_steps = [
authorize_if: [author1: [id: 1]],
forbid_if: [author1: [allow_second_author: false]],
authorize_if: [author2: [id: 1]]
]
describe "simple attribute 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})
Ash.Filter.SatSolver.solve(Post, authorization_steps)
%{post1: post1, post2: post2}
end
# Api.read(Post,
# filter: [
# title: "foo",
# title: "bar",
# contents: [in: ["bar", "baz"]],
# contents: [in: ["foo", "bar"]],
# author1: [id: 1],
# author2: [name: "bob"]
# ]
# )
test "single filter field", %{post1: post1} do
assert %{results: [^post1]} =
Api.read!(Post,
filter: [
title: post1.title
]
)
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