mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 21:43:02 +12:00
e36f8c3e59
improvement: add data layer capability for aggregate relationships & filter relationships improvement: add guide on manual relationships
273 lines
6.6 KiB
Elixir
273 lines
6.6 KiB
Elixir
defmodule Ash.Test.SeedTest do
|
|
@moduledoc false
|
|
use ExUnit.Case, async: true
|
|
|
|
import Ash.Seed
|
|
require Ash.Query
|
|
|
|
defmodule Author do
|
|
@moduledoc false
|
|
use Ash.Resource,
|
|
data_layer: Ash.DataLayer.Ets
|
|
|
|
ets do
|
|
private?(true)
|
|
end
|
|
|
|
actions do
|
|
defaults [:create, :read, :update, :destroy]
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :name, :string, default: "Fred"
|
|
end
|
|
|
|
relationships do
|
|
has_many :posts, Ash.Test.SeedTest.Post, destination_attribute: :author_id
|
|
|
|
has_one :latest_post, Ash.Test.SeedTest.Post,
|
|
destination_attribute: :author_id,
|
|
sort: [inserted_at: :desc]
|
|
end
|
|
end
|
|
|
|
defmodule Post do
|
|
@moduledoc false
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
ets do
|
|
private?(true)
|
|
end
|
|
|
|
actions do
|
|
defaults [:create, :read, :update, :destroy]
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :title, :string
|
|
attribute :contents, :string
|
|
attribute :category, :string
|
|
timestamps()
|
|
end
|
|
|
|
relationships do
|
|
belongs_to :author, Author
|
|
|
|
has_many :ratings, Ash.Test.SeedTest.Rating do
|
|
api Ash.Test.SeedTest.Api2
|
|
end
|
|
|
|
many_to_many :categories, Ash.Test.SeedTest.Category,
|
|
through: Ash.Test.SeedTest.PostCategory,
|
|
destination_attribute_on_join_resource: :category_id,
|
|
source_attribute_on_join_resource: :post_id
|
|
end
|
|
end
|
|
|
|
defmodule PostCategory do
|
|
@moduledoc false
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
ets do
|
|
private?(true)
|
|
end
|
|
|
|
actions do
|
|
defaults [:create, :read, :update, :destroy]
|
|
end
|
|
|
|
relationships do
|
|
belongs_to :post, Post, primary_key?: true, allow_nil?: false
|
|
|
|
belongs_to :category, Ash.Test.SeedTest.Category,
|
|
primary_key?: true,
|
|
allow_nil?: false
|
|
end
|
|
end
|
|
|
|
defmodule Category do
|
|
@moduledoc false
|
|
use Ash.Resource, data_layer: Ash.DataLayer.Ets
|
|
|
|
ets do
|
|
private?(true)
|
|
end
|
|
|
|
actions do
|
|
defaults [:create, :read, :update, :destroy]
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :name, :string
|
|
end
|
|
|
|
relationships do
|
|
many_to_many :posts, Post,
|
|
through: PostCategory,
|
|
destination_attribute_on_join_resource: :post_id,
|
|
source_attribute_on_join_resource: :category_id
|
|
end
|
|
end
|
|
|
|
defmodule Rating do
|
|
use Ash.Resource,
|
|
data_layer: Ash.DataLayer.Ets
|
|
|
|
ets do
|
|
private? true
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :rating, :integer
|
|
end
|
|
|
|
actions do
|
|
defaults [:create, :read, :update, :destroy]
|
|
end
|
|
|
|
relationships do
|
|
belongs_to :post, Post do
|
|
api Ash.Test.SeedTest.Category
|
|
end
|
|
end
|
|
end
|
|
|
|
defmodule Registry do
|
|
@moduledoc false
|
|
use Ash.Registry
|
|
|
|
entries do
|
|
entry(Author)
|
|
entry(Post)
|
|
entry(Category)
|
|
entry(PostCategory)
|
|
end
|
|
end
|
|
|
|
defmodule Registry2 do
|
|
@moduledoc false
|
|
use Ash.Registry
|
|
|
|
entries do
|
|
entry(Rating)
|
|
end
|
|
end
|
|
|
|
defmodule Api do
|
|
@moduledoc false
|
|
use Ash.Api
|
|
|
|
resources do
|
|
registry Registry
|
|
end
|
|
end
|
|
|
|
defmodule Api2 do
|
|
@moduledoc false
|
|
use Ash.Api
|
|
|
|
resources do
|
|
registry Registry2
|
|
end
|
|
end
|
|
|
|
describe "seed!/1" do
|
|
test "it creates a single record with resource and input" do
|
|
assert %Post{id: id, title: "seeded"} = seed!(Post, %{title: "seeded"})
|
|
|
|
assert post = Api.get!(Post, id)
|
|
assert post.title == "seeded"
|
|
end
|
|
|
|
test "it creates a single record with a struct" do
|
|
assert %Post{id: id, title: "seeded"} = seed!(%Post{title: "seeded"})
|
|
|
|
assert post = Api.get!(Post, id)
|
|
assert post.title == "seeded"
|
|
end
|
|
|
|
test "defaults are set when using a struct" do
|
|
assert %Author{name: "Fred"} = seed!(%Author{})
|
|
assert %Author{name: "Fred"} = seed!(%Author{})
|
|
end
|
|
|
|
test "it creates related entities" do
|
|
assert %Post{
|
|
id: id,
|
|
title: "seeded",
|
|
categories: [%Category{name: "foo"}, %Category{name: "bar"}],
|
|
author: %Author{name: "ted dansen"},
|
|
ratings: [%Rating{rating: 1}, %Rating{rating: 2}]
|
|
} =
|
|
seed!(%Post{
|
|
title: "seeded",
|
|
categories: [%Category{name: "foo"}, %Category{name: "bar"}],
|
|
author: %Author{name: "ted dansen"},
|
|
ratings: [%Rating{rating: 1}, %Rating{rating: 2}]
|
|
})
|
|
|
|
assert %Post{
|
|
id: ^id,
|
|
title: "seeded",
|
|
categories: categories,
|
|
author: %Author{name: "ted dansen"},
|
|
ratings: ratings
|
|
} = Post |> Api.get!(id) |> Api.load!([:categories, :author, :ratings])
|
|
|
|
assert categories |> Enum.map(& &1.name) |> Enum.sort() == ["bar", "foo"]
|
|
assert ratings |> Enum.map(& &1.rating) |> Enum.sort() == [1, 2]
|
|
end
|
|
|
|
test "it reuses entities that have been loaded (doesnt try to create a copy)" do
|
|
assert %Post{
|
|
id: id,
|
|
title: "seeded",
|
|
categories: [%Category{name: "foo"}, %Category{name: "bar"}],
|
|
author: %Author{name: "ted dansen"},
|
|
ratings: [%Rating{rating: 1}, %Rating{rating: 2}]
|
|
} =
|
|
seed!(%Post{
|
|
title: "seeded",
|
|
categories: [%Category{name: "foo"}, %Category{name: "bar"}],
|
|
author: %Author{name: "ted dansen"},
|
|
ratings: [%Rating{rating: 1}, %Rating{rating: 2}]
|
|
})
|
|
|
|
assert %Post{
|
|
id: ^id,
|
|
title: "seeded",
|
|
categories: categories,
|
|
author: author,
|
|
ratings: ratings
|
|
} = Post |> Api.get!(id) |> Api.load!([:categories, :author, :ratings])
|
|
|
|
assert %Post{id: id} =
|
|
seed!(%Post{
|
|
title: "seeded2",
|
|
categories: categories,
|
|
author: author,
|
|
ratings: ratings
|
|
})
|
|
|
|
assert %Post{
|
|
id: ^id,
|
|
title: "seeded2",
|
|
categories: categories,
|
|
author: author,
|
|
ratings: ratings
|
|
} = Post |> Api.get!(id) |> Api.load!([:categories, :author, :ratings])
|
|
|
|
assert categories |> Enum.map(& &1.name) |> Enum.sort() == ["bar", "foo"]
|
|
assert ratings |> Enum.map(& &1.rating) |> Enum.sort() == [1, 2]
|
|
assert author.name == "ted dansen"
|
|
|
|
assert Enum.count(Api.read!(Category)) == 2
|
|
assert Enum.count(Api.read!(Rating)) == 2
|
|
assert Enum.count(Api.read!(Author)) == 1
|
|
end
|
|
end
|
|
end
|