defmodule Ash.Resource.Actions.Read do
@moduledoc "Represents a read action on a resource."
defstruct [
:name,
:pagination,
:primary?,
:filter,
:description,
:get?,
:manual,
modify_query: nil,
transaction?: false,
arguments: [],
preparations: [],
touches_resources: [],
metadata: [],
type: :read
]
@type t :: %__MODULE__{
type: :read,
name: atom,
manual: atom | {atom, Keyword.t()} | nil,
primary?: boolean,
touches_resources: list(atom),
description: String.t()
}
import Ash.Resource.Actions.SharedOptions
@global_opts shared_options()
@opt_schema Spark.OptionsHelpers.merge_schemas(
[
filter: [
type: :any,
doc:
"A filter template that will be applied whenever the action is used. See `Ash.Filter` for more on templates"
],
manual: [
type:
{:spark_function_behaviour, Ash.Resource.ManualRead,
{Ash.Resource.ManualRead.Function, 3}},
doc: """
Delegates running of the query to the provided module.
Accepts a module or module and opts, or a function that takes the changeset and context.
See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
"""
],
get?: [
type: :boolean,
default: false,
doc: """
Expresses that this action innately only returns a single result. Can be used by extensions to validate that you have not hooked something up that expects a list
to an action that can only return one thing. Used by the code interface when defining functions for read actions.
See the [code interface guide](/documentation/topics/code-interface.md) for more.
"""
],
modify_query: [
type: :mfa,
doc: """
Allows direct manipulation of the data layer query via an MFA.
The ash query and the data layer query will be provided as additional arguments.
The result must be `{:ok, new_data_layer_query} | {:error, error}`.
Here be dragons.
"""
]
],
@global_opts,
"Action Options"
)
@pagination_schema [
keyset?: [
type: :boolean,
doc: "Whether or not keyset based pagination is supported",
default: false
],
offset?: [
type: :boolean,
doc: "Whether or not offset based pagination is supported",
default: false
],
default_limit: [
type: :pos_integer,
doc: "The default page size to apply, if one is not supplied"
],
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
],
max_page_size: [
type: :pos_integer,
doc: "The maximum amount of records that can be requested in a single page",
default: 250
],
required?: [
type: :boolean,
doc:
"Whether or not pagination can be disabled. Only relevant if some pagination configuration is supplied.",
default: true
]
]
defmodule Pagination do
@moduledoc "Represents the pagination configuration of a read action"
defstruct [
:default_limit,
:max_page_size,
countable: false,
required?: false,
keyset?: false,
offset?: false
]
def transform(pagination) do
if pagination.keyset? or pagination.offset? do
{:ok, pagination}
else
{:error, "Must enable `keyset?` or `offset?`"}
end
end
end
def transform(read) do
if read.pagination do
{:ok, %{read | pagination: List.last(read.pagination) || false}}
else
{:ok, %{read | pagination: false}}
end
end
@doc false
def opt_schema, do: @opt_schema
def pagination_schema, do: @pagination_schema
end