chore: failing test for calculation ordered paginated relationship (#292)

This commit is contained in:
Riccardo Binetti 2024-05-20 16:06:49 +02:00 committed by GitHub
parent 06f0f9befe
commit 0313734db0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 234 additions and 0 deletions

View file

@ -0,0 +1,85 @@
{
"attributes": [
{
"default": "nil",
"size": null,
"type": "bigint",
"source": "order",
"references": null,
"allow_nil?": true,
"generated?": false,
"primary_key?": false
},
{
"default": "nil",
"size": null,
"type": "uuid",
"source": "post_id",
"references": {
"name": "post_followers_post_id_fkey",
"table": "posts",
"schema": "public",
"on_delete": null,
"multitenancy": {
"global": null,
"attribute": null,
"strategy": null
},
"primary_key?": true,
"destination_attribute": "id",
"on_update": null,
"deferrable": false,
"match_type": null,
"match_with": null,
"destination_attribute_default": null,
"destination_attribute_generated": null
},
"allow_nil?": false,
"generated?": false,
"primary_key?": true
},
{
"default": "nil",
"size": null,
"type": "uuid",
"source": "follower_id",
"references": {
"name": "post_followers_follower_id_fkey",
"table": "users",
"schema": "public",
"on_delete": null,
"multitenancy": {
"global": null,
"attribute": null,
"strategy": null
},
"primary_key?": true,
"destination_attribute": "id",
"on_update": null,
"deferrable": false,
"match_type": null,
"match_with": null,
"destination_attribute_default": null,
"destination_attribute_generated": null
},
"allow_nil?": false,
"generated?": false,
"primary_key?": true
}
],
"table": "post_followers",
"hash": "90A18FEF426DFEB27D87699FD791652300BCB4DE52BC43FBE71A571A596723CF",
"repo": "Elixir.AshPostgres.TestRepo",
"identities": [],
"schema": null,
"check_constraints": [],
"custom_indexes": [],
"base_filter": null,
"multitenancy": {
"global": null,
"attribute": null,
"strategy": null
},
"custom_statements": [],
"has_create_action": true
}

View file

@ -0,0 +1,21 @@
defmodule AshPostgres.TestRepo.Migrations.MigrateResources24 do
@moduledoc """
Updates resources based on their most recent snapshots.
This file was autogenerated with `mix ash_postgres.generate_migrations`
"""
use Ecto.Migration
def up do
alter table(:post_followers) do
add(:order, :bigint)
end
end
def down do
alter table(:post_followers) do
remove(:order)
end
end
end

View file

@ -531,6 +531,117 @@ defmodule AshPostgres.Test.LoadTest do
} = Ash.page!(post1.followers, :next)
end
test "it allows paginating calculation ordered many_to_many relationships with offset" do
followers =
for i <- 0..9 do
User
|> Ash.Changeset.for_create(:create, %{name: "user#{i}", is_active: true})
|> Ash.create!()
end
followers_0_to_6_reversed =
Enum.take(followers, 7)
|> Enum.with_index()
|> Enum.map(fn {follower, idx} -> %{id: follower.id, order: 6 - idx} end)
followers_5_to_9_reversed =
Enum.slice(followers, 5..9)
|> Enum.with_index()
|> Enum.map(fn {follower, idx} -> %{id: follower.id, order: 9 - idx} end)
Post
|> Ash.Changeset.for_create(:create, %{title: "a"})
|> Ash.Changeset.manage_relationship(:followers, followers_0_to_6_reversed,
on_lookup: {:relate_and_update, :create, :read, [:order]}
)
|> Ash.create!()
Post
|> Ash.Changeset.for_create(:create, %{title: "b"})
|> Ash.Changeset.manage_relationship(:followers, followers_5_to_9_reversed,
on_lookup: {:relate_and_update, :create, :read, [:order]}
)
|> Ash.create!()
paginated_sorted_followers =
User
|> Ash.Query.page(limit: 2)
assert [post1, post2] =
Post
|> Ash.Query.sort(:title)
|> Ash.Query.load(sorted_followers: paginated_sorted_followers)
|> Ash.read!()
assert %Ash.Page.Offset{
results: [%{name: "user6"}, %{name: "user5"}]
} = post1.sorted_followers
assert %Ash.Page.Offset{
results: [%{name: "user9"}, %{name: "user8"}]
} = post2.sorted_followers
assert %Ash.Page.Offset{
results: [%{name: "user4"}, %{name: "user3"}]
} = Ash.page!(post1.sorted_followers, :next)
end
test "it allows paginating calculation ordered many_to_many relationships with keyset" do
followers =
for i <- 0..9 do
User
|> Ash.Changeset.for_create(:create, %{name: "user#{i}", is_active: true})
|> Ash.create!()
end
followers_0_to_6_reversed =
Enum.take(followers, 7)
|> Enum.with_index()
|> Enum.map(fn {follower, idx} -> %{id: follower.id, order: 6 - idx} end)
followers_5_to_9_reversed =
Enum.slice(followers, 5..9)
|> Enum.with_index()
|> Enum.map(fn {follower, idx} -> %{id: follower.id, order: 9 - idx} end)
Post
|> Ash.Changeset.for_create(:create, %{title: "a"})
|> Ash.Changeset.manage_relationship(:followers, followers_0_to_6_reversed,
on_lookup: {:relate_and_update, :create, :read, [:order]}
)
|> Ash.create!()
Post
|> Ash.Changeset.for_create(:create, %{title: "b"})
|> Ash.Changeset.manage_relationship(:followers, followers_5_to_9_reversed,
on_lookup: {:relate_and_update, :create, :read, [:order]}
)
|> Ash.create!()
paginated_sorted_followers =
User
|> Ash.Query.for_read(:keyset)
|> Ash.Query.page(limit: 2)
assert [post1, post2] =
Post
|> Ash.Query.sort(:title)
|> Ash.Query.load(sorted_followers: paginated_sorted_followers)
|> Ash.read!()
assert %Ash.Page.Keyset{
results: [%{name: "user6"}, %{name: "user5"}]
} = post1.sorted_followers
assert %Ash.Page.Keyset{
results: [%{name: "user9"}, %{name: "user8"}]
} = post2.sorted_followers
assert %Ash.Page.Keyset{
results: [%{name: "user4"}, %{name: "user3"}]
} = Ash.page!(post1.sorted_followers, :next)
end
test "works when nested with offset" do
author1 =
Author

View file

@ -22,6 +22,8 @@ defmodule AshPostgres.Test.Post do
Ash.Policy.Authorizer
]
require Ash.Sort
policies do
bypass action_type(:read) do
# Check that the post is in the same org as actor
@ -312,6 +314,17 @@ defmodule AshPostgres.Test.Post do
read_action: :active
)
has_many(:post_followers, AshPostgres.Test.PostFollower)
many_to_many(:sorted_followers, AshPostgres.Test.User,
public?: true,
through: AshPostgres.Test.PostFollower,
join_relationship: :post_followers,
source_attribute_on_join_resource: :post_id,
destination_attribute_on_join_resource: :follower_id,
sort: [Ash.Sort.expr_sort(parent(post_followers.order))]
)
has_many(:views, AshPostgres.Test.PostView) do
public?(true)
end

View file

@ -15,6 +15,10 @@ defmodule AshPostgres.Test.PostFollower do
defaults([:create, :read, :update, :destroy])
end
attributes do
attribute(:order, :integer, public?: true)
end
relationships do
belongs_to :post, AshPostgres.Test.Post do
primary_key?(true)