fix: honor the countable option in pagination

the default unfortunately had to be changed to `true`, given that it was being ignored before

chore: clean up error declarations
This commit is contained in:
Zach Daniel 2024-08-30 15:34:40 -04:00
parent 0007d0e60a
commit 9b0fb15ecb
24 changed files with 34 additions and 29 deletions

View file

@ -2,7 +2,7 @@ defmodule Ash.Actions.Read do
@moduledoc false
alias Ash.Actions.Helpers
alias Ash.Error.Invalid.{LimitRequired, PaginationRequired}
alias Ash.Error.Invalid.{LimitRequired, NonCountableAction, PaginationRequired}
alias Ash.Filter
require Logger
@ -2367,6 +2367,10 @@ defmodule Ash.Actions.Read do
{:ok, starting_query}
end
page_opts[:count] == true && !action.pagination.countable ->
{:error,
NonCountableAction.exception(resource: starting_query.resource, action: action.name)}
page_opts[:limit] ->
page_opts =
Keyword.put(

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Action.InvalidArgument do
@moduledoc "Used when an invalid value is provided for an action argument"
use Ash.Error.Exception
use Splode.Error, fields: [:field, :message, :value], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.ActionRequiresActor do
@moduledoc "Used when an actor is referenced in a filter template, but no actor exists"
use Ash.Error.Exception
use Splode.Error, fields: [], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.InvalidArgument do
@moduledoc "Used when an invalid value is provided for an action argument"
use Ash.Error.Exception
use Splode.Error, fields: [:field, :message, :value], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.InvalidAttribute do
@moduledoc "Used when an invalid value is provided for an attribute change"
use Ash.Error.Exception
use Splode.Error, fields: [:field, :message, :private_vars, :value], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.InvalidChanges do
@moduledoc "Used when a change is provided that covers multiple attributes/relationships"
use Ash.Error.Exception
use Splode.Error, fields: [:fields, :message, :validation, :value], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.InvalidRelationship do
@moduledoc "Used when an invalid value is provided for a relationship change"
use Ash.Error.Exception
use Splode.Error, fields: [:relationship, :message], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.NoSuchAttribute do
@moduledoc "Used when a change is provided for an attribute that does not exist"
use Ash.Error.Exception
use Splode.Error, fields: [:resource, :attribute], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.NoSuchRelationship do
@moduledoc "Used when a change is provided for an relationship that does not exist"
use Ash.Error.Exception
use Splode.Error, fields: [:resource, :relationship], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.Required do
@moduledoc "Used when an attribute or relationship is required"
use Ash.Error.Exception
use Splode.Error, fields: [:field, :type, :resource], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Changes.StaleRecord do
@moduledoc "Used when a stale record is attempted to be updated or deleted"
use Ash.Error.Exception
use Splode.Error, fields: [:resource, :filter], class: :invalid

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Forbidden.CannotFilterCreates do
@moduledoc "Used when a create action would be filtered"
use Ash.Error.Exception
use Splode.Error, fields: [], class: :forbidden

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Forbidden.DomainRequiresActor do
@moduledoc "Used when a domain that has `require_actor? true` is provided no actor"
use Ash.Error.Exception
use Splode.Error, fields: [:domain], class: :forbidden

View file

@ -1,6 +1,5 @@
defmodule Ash.Error.Forbidden.DomainRequiresAuthorization do
@moduledoc "Used when a domain that has `authorize :always` is provided authorize?: false"
use Ash.Error.Exception
use Splode.Error, fields: [:domain], class: :forbidden

View file

@ -2,7 +2,6 @@ defmodule Ash.Error.Forbidden.ForbiddenField do
@moduledoc "Raised in cases where access to a specific field was prevented"
require Logger
use Ash.Error.Exception
use Splode.Error, fields: [:resource, :field], class: :forbidden

View file

@ -1,7 +1,5 @@
defmodule Ash.Error.Forbidden.InitialDataRequired do
@moduledoc "Used when "
use Ash.Error.Exception
@moduledoc "Used when initial data was not supplied when it was required"
use Splode.Error, fields: [:source], class: :forbidden
def message(%{source: source}) do

View file

@ -1,7 +1,5 @@
defmodule Ash.Error.Forbidden.MustPassStrictCheck do
@moduledoc "Used when unreachable code/conditions are reached in the framework"
use Ash.Error.Exception
use Splode.Error, fields: [], class: :forbidden
def message(_) do

View file

@ -1,7 +1,5 @@
defmodule Ash.Error.Forbidden.Placeholder do
@moduledoc "A placeholder exception that the user should never see"
use Ash.Error.Exception
use Splode.Error, fields: [:authorizer], class: :forbidden
def from_json(%{"authorizer" => authorizer}) do

View file

@ -1,7 +1,5 @@
defmodule Ash.Error.Framework.AssumptionFailed do
@moduledoc "Used when unreachable code/conditions are reached in the framework"
use Ash.Error.Exception
use Splode.Error, fields: [:message], class: :framework
def message(%{message: message}) do

View file

@ -1,7 +1,5 @@
defmodule Ash.Error.Framework.CanNotBeAtomic do
@moduledoc "Used when a change that is only atomic cannot be done atomically"
use Ash.Error.Exception
use Splode.Error, fields: [:resource, :change, :reason], class: :framework
def message(error) do

View file

@ -1,7 +1,5 @@
defmodule Ash.Error.Framework.FlagAssertionFailed do
@moduledoc "Used when unreachable code/conditions are reached in the framework"
use Ash.Error.Exception
use Splode.Error, fields: [:flag, :heading], class: :framework
def message(error) do

View file

@ -0,0 +1,8 @@
defmodule Ash.Error.Invalid.NonCountableAction do
@moduledoc "Used when page[:count] option is passed but the action's pagination is not countable."
use Splode.Error, fields: [:resource, :action], class: :invalid
def message(%{resource: resource, action: action}) do
"Action #{inspect(resource)}.#{action} cannot be counted while paginating but a count was requested."
end
end

View file

@ -109,11 +109,12 @@ defmodule Ash.Resource.Actions.Read do
type: :pos_integer,
doc: "The default page size to apply, if one is not supplied"
],
# Change this default in 4.0
countable: [
type: {:in, [true, false, :by_default]},
doc:
"Whether not a returned page will have a full count of all records. Use `:by_default` to do it automatically.",
default: false
default: true
],
max_page_size: [
type: :pos_integer,

View file

@ -21,6 +21,14 @@ defmodule Ash.Test.CountTest do
default_limit 5
end
end
read :non_countable do
pagination do
offset? true
default_limit 5
countable false
end
end
end
ets do
@ -77,4 +85,14 @@ defmodule Ash.Test.CountTest do
assert count == 10
end
test "trying to count a non-countable action is invalid" do
assert_raise Ash.Error.Invalid,
~r/cannot be counted while paginating/,
fn ->
Countable
|> Ash.Query.for_read(:non_countable)
|> Ash.read!(actor: %{id: "foo"}, page: [count: true])
end
end
end