mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 05:23:03 +12:00
docs: remove the word simply
from the docs
This commit is contained in:
parent
1e6be17618
commit
652342c41d
30 changed files with 45 additions and 52 deletions
|
@ -11,7 +11,7 @@ While still more experimental than the rest of the framework, Ash.Flow is no lon
|
|||
### New DSL tooling
|
||||
|
||||
The DSL tooling has been moved out of the Ash name space and into a more generalized tool called `Spark`. If you have written your own extensions, you will need
|
||||
to refer to those modules. They are all the same, they simply have different names. You will get compiler errors/warnings on the modules you need to change, for example: `Ash.Dsl` -> `Spark.Dsl` and `Ash.Dsl.Transformer` -> `Spark.Dsl.Transformer`. One exception, `Ash.Error.Dsl.DslError`, has been changed to `Spark.Error.DslError`.
|
||||
to refer to those modules. They are all the same, but they have different names. You will get compiler errors/warnings on the modules you need to change, for example: `Ash.Dsl` -> `Spark.Dsl` and `Ash.Dsl.Transformer` -> `Spark.Dsl.Transformer`. One exception, `Ash.Error.Dsl.DslError`, has been changed to `Spark.Error.DslError`.
|
||||
|
||||
## DSL name changes
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Use Without Data Layers
|
||||
|
||||
If a resource is configured without a data layer, then it will always be working off of a temporary data set that lives only for the life of that query. This can be a powerful way to simply model input validations and/or custom/complex reads. Technically, resources without a data layer simply use `Ash.DataLayer.Simple`, which does no persistence, and expects to find any data it should use for read actions in a context on the query
|
||||
If a resource is configured without a data layer, then it will always be working off of a temporary data set that lives only for the life of that query. This can be a powerful way to model input validations and/or custom/complex reads. Technically, resources without a data layer use `Ash.DataLayer.Simple`, which does no persistence, and expects to find any data it should use for read actions in a context on the query
|
||||
|
||||
## Example
|
||||
|
||||
|
@ -10,7 +10,7 @@ defmodule MyApp.MyComplexResource do
|
|||
# notice no data layer is configured
|
||||
|
||||
attributes do
|
||||
#A primary key is always necessary on a resource, but this will simply generate one for you automatically
|
||||
#A primary key is always necessary on a resource, but this will generate one for you automatically
|
||||
uuid_primary_key :id
|
||||
attribute :some_complex_derived_number, :integer
|
||||
end
|
||||
|
@ -51,7 +51,7 @@ They are used in exactly the same way as regular resources
|
|||
changeset =
|
||||
Ash.Changeset.for_create(MyApp.FetchComplexResource, :validate_input, %{})
|
||||
|
||||
# This will simply return the structs by default
|
||||
# This will return the structs by default
|
||||
# Although you are free to do custom persistence in your resource changes
|
||||
MyApp.MyApi.create!(changeset)
|
||||
# %MyApp.FetchComplexResource{...}
|
||||
|
|
|
@ -41,7 +41,7 @@ The only information available is the changeset. If you want to adjust the behav
|
|||
on other details of the request, like the current user, you are most likely looking for
|
||||
authorization.
|
||||
|
||||
A validation is simply a module that implements the `Ash.Resource.Validation` behaviour. The built in validations
|
||||
A validation is a module that implements the `Ash.Resource.Validation` behaviour. The built in validations
|
||||
expose utility functions that are imported into the resource's scope, to make them easier to read. You
|
||||
can do this with custom validations as well. See the documentation in `Ash.Resource.Validation` for more information.
|
||||
Right now, there are not very many built in validations, but the idea is that eventually we will have a rich
|
||||
|
|
|
@ -31,7 +31,7 @@ A simple example where a primary action would be used:
|
|||
Api.get!(Resource, "8ba0ab56-c6e3-4ab0-9c9c-df70e9945281")
|
||||
```
|
||||
|
||||
To mark an action as primary, simply add the option, i.e
|
||||
To mark an action as primary, add the option, i.e
|
||||
|
||||
```elixir
|
||||
read :action_name do
|
||||
|
@ -82,7 +82,7 @@ read :top do
|
|||
end
|
||||
```
|
||||
|
||||
Now, whatever code I had that would have called `top_tickets/1` can now simply call `Helpdesk.Support.Ticket.top(user.id)`. By doing it this way, you get the primary benefit of getting a nice simple Api to call into, but you *also* have a way to modify how the action is invoked in any way necessary, by going back to the old way of simply building the query. For example, if I also only want to see top tickets that were opened in the last 10 minutes:
|
||||
Now, whatever code I had that would have called `top_tickets/1` can now call `Helpdesk.Support.Ticket.top(user.id)`. By doing it this way, you get the primary benefit of getting a nice simple Api to call into, but you *also* have a way to modify how the action is invoked in any way necessary, by going back to the old way of building the query manually. For example, if I also only want to see top tickets that were opened in the last 10 minutes:
|
||||
|
||||
```elixir
|
||||
Ticket
|
||||
|
|
|
@ -11,7 +11,7 @@ data.
|
|||
|
||||
### Expression Calculations
|
||||
|
||||
The simplest kind of calculation simply refers to an Ash expression. For example:
|
||||
The simplest kind of calculation refers to an Ash expression. For example:
|
||||
|
||||
```elixir
|
||||
calculations do
|
||||
|
|
|
@ -20,8 +20,7 @@ Embedded resources cannot have relationships or aggregates.
|
|||
|
||||
## Adding embedded resource attributes
|
||||
|
||||
Embedded resources simply define an `Ash.Type` under the hood, meaning you can use them anywhere you would
|
||||
use an Ash type.
|
||||
Embedded resources define an `Ash.Type` under the hood, meaning you can use them anywhere you would use an Ash type.
|
||||
|
||||
```elixir
|
||||
defmodule MyApp.User do
|
||||
|
@ -144,7 +143,7 @@ Now, you can accept input meant to `update` individual list items. The entire li
|
|||
|
||||
#### Single Embeds with primary keys
|
||||
|
||||
* If you provide a struct, instead of a map, the value provided is simply used as the new relationship value.
|
||||
* If you provide a struct, instead of a map, the value provided is used as the new relationship value directly.
|
||||
* If the current value is `nil` - a `create` with the provided values
|
||||
* If the current value is not `nil` and the primary keys match - an `update` with the provided values
|
||||
* If the current value is not `nil` and the primary keys *don't* match - a `destroy` of the original value and a `create` of the new value
|
||||
|
@ -152,7 +151,7 @@ Now, you can accept input meant to `update` individual list items. The entire li
|
|||
|
||||
#### Array Embeds with primary keys
|
||||
|
||||
* If you provide structs, instead of maps, the value provided is simply used as the new relationship value.
|
||||
* If you provide structs, instead of maps, the value provided is used as the new relationship value directly.
|
||||
* Any values in the original list with no primary key matching in the new list are `destroy`ed.
|
||||
* Any values in the new list with no primary key matching in the original list are `create`d.
|
||||
* Any values with a primary key match in the original list and the new list are `update`d
|
||||
|
@ -163,7 +162,7 @@ Identities can be added on an embedded resource, which will ensure that for any
|
|||
|
||||
## Usage in Extensions
|
||||
|
||||
The AshJsonApi extension simply exposes these attributes as maps. However, the AshGraphql extension allows you
|
||||
The AshJsonApi extension exposes these attributes as maps. However, the AshGraphql extension allows you
|
||||
to specify a type (but not queries/mutations) for an embedded resource. If you do, instead of being treated as a `:json` type it will get its own named input object type and field type.
|
||||
|
||||
## Accessing the source changeset
|
||||
|
|
|
@ -156,7 +156,7 @@ You would see that it ran a SQL query with the `full_name` calculation as SQL. T
|
|||
Accounts.load!(user, :full_name)
|
||||
```
|
||||
|
||||
you would see that no SQL queries are run. The calculation is simply run in Elixir and the value is set.
|
||||
you would see that no SQL queries are run. The calculation is run directly in Elixir and the value is set.
|
||||
|
||||
### Referencing related values
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ end
|
|||
|
||||
## Errors
|
||||
|
||||
Currently, any error anywhere in the flow will simply fail the flow and will return an error. Over time, error handling behavior will be added, as well as the ability to customize how transactions are rolled back, and to handle errors in a custom way.
|
||||
Currently, any error anywhere in the flow will fail the flow and will return an error. Over time, error handling behavior will be added, as well as the ability to customize how transactions are rolled back, and to handle errors in a custom way.
|
||||
|
||||
## Custom steps
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ actions do
|
|||
end
|
||||
```
|
||||
|
||||
With this, those arguments can be used simply in action input:
|
||||
With this, those arguments can be used in action input:
|
||||
|
||||
```elixir
|
||||
post
|
||||
|
|
|
@ -35,7 +35,7 @@ end
|
|||
## Manual Read Actions
|
||||
|
||||
Manual read actions work differently. They must be provided a module that will run the read action.
|
||||
The module should implement the `Ash.Resource.ManualRead` behaviour, and actions will simply be handed the ash query and the data layer query.
|
||||
The module should implement the `Ash.Resource.ManualRead` behaviour, and actions will be handed the ash query and the data layer query.
|
||||
|
||||
```elixir
|
||||
# in the resource
|
||||
|
|
|
@ -11,7 +11,7 @@ MyApp.MyApi.read(MyResource, actor: current_user)
|
|||
## Important!
|
||||
|
||||
Before we jump into the guide, it is critical to understand that the policy code doesn't actually
|
||||
_do_ anything in the classic sense. It simply builds up a set of policies that are stored for use later.
|
||||
_do_ anything in the classic sense. It only builds up a set of policies that are stored for use later.
|
||||
The checker that reads those policies and authorizes requests may run all, some of, or none of your checks,
|
||||
depending on the details of the request being authorized.
|
||||
|
||||
|
@ -130,7 +130,7 @@ Depending on the action type these expressions behave slightly differently.
|
|||
### Access Type
|
||||
|
||||
The default access type is `:filter`. In most cases this will be all you need. In the example above, if a user made a request for all instances
|
||||
of the resource, it wouldn't actually return a forbidden error. It simply attaches the appropriate filter to fetch data that the user can see.
|
||||
of the resource, it wouldn't actually return a forbidden error. Instead, it attaches the appropriate filter to fetch data that the user can see.
|
||||
If the actor attribute `active` was `false`, then the request _would_ be forbidden (because there is no data for which they can pass this policy). However, if `active` is `true`, the authorizer would attach the following filter to the request:
|
||||
|
||||
```elixir
|
||||
|
@ -157,7 +157,7 @@ Here is an example policy breakdown from tests:
|
|||
```text
|
||||
Policy Breakdown
|
||||
A check status of `?` implies that the solver did not need to determine that check.
|
||||
Some checks may look like they failed when in reality there was simply no need to check them.
|
||||
Some checks may look like they failed when in reality there was no need to check them.
|
||||
Look for policies with `✘` and `✓` in check statuses.
|
||||
|
||||
A check with a `⬇` means that it didn't determine if the policy was authorized or forbidden, and so moved on to the next check.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Ash includes a builtin notifier to help you publish events over any kind of pub-sub pattern. This is plug and play with `Phoenix.PubSub`, but could be used with any pubsub pattern.
|
||||
|
||||
You simply configure a module that defines a `broadcast/3` function, and then add some "publications" which configure under what conditions an event should be sent and what the topic should be.
|
||||
You configure a module that defines a `broadcast/3` function, and then add some "publications" which configure under what conditions an event should be sent and what the topic should be.
|
||||
|
||||
## Topic Templates
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ Timeouts in Ash work a bit differently than other tools. The following considera
|
|||
2. If the resource action you are running, and any of its `touches_resources` is *already in a transaction* then the timeout is ignored, as the outer transaction is handling the timeout.
|
||||
3. If the resource is not in a transaction, and supports async execution (ash_postgres does), then everything is run in a task and awaited with the provided timeout.
|
||||
4. If the data layer of the resource does not support timeouts, or async execution then timeouts are **ignored**.
|
||||
5. As of the writing of this guide, none of the API extensions support specifying a timeout. If/when they do, they will simply run the action they are meant to run in a `Task`.
|
||||
5. As of the writing of this guide, none of the API extensions support specifying a timeout. If/when they do, they will run the action they are meant to run in a `Task`.
|
||||
|
||||
## Ways to Specify Timeouts
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ Before we get into working with relationships, lets add some actual persistence
|
|||
|
||||
There is a built in data layer that is good for testing and prototyping, that uses [ETS](https://elixir-lang.org/getting-started/mix-otp/ets.html).
|
||||
|
||||
To add it to your resource, simply modify it like so:
|
||||
To add it to your resource, modify it like so:
|
||||
|
||||
```elixir
|
||||
use Ash.Resource,
|
||||
|
|
|
@ -8,7 +8,7 @@ The philosophy behind Ash allows us to build an extremely flexible and powerful
|
|||
|
||||
## Declarative, Introspectable, Derivable
|
||||
|
||||
The real superpower behind Ash is the declarative design pattern. All behavior is driven by explicit, static declarations. A resource, for example, is really just a configuration file. On its own it does nothing, it is simply provided to code that reads that configuration and acts accordingly. You can read more about some simple declarative design patterns outside of the context of Ash Framework in [An Incremental Approach to Declarative Design](https://zachdaniel.dev/incremental-declarative-design/).
|
||||
The real superpower behind Ash is the declarative design pattern. All behavior is driven by explicit, static declarations. A resource, for example, is really just a configuration file. On its own it does nothing. It is provided to code that reads that configuration and acts accordingly. You can read more about some simple declarative design patterns outside of the context of Ash Framework in [An Incremental Approach to Declarative Design](https://zachdaniel.dev/incremental-declarative-design/).
|
||||
|
||||
## Pragmatism First
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ defmodule Ash.Actions.Helpers do
|
|||
Missed #{Enum.count(missed)} notifications in action #{inspect(resource)}.#{action.name}.
|
||||
|
||||
This happens when the resources are in a transaction, and you did not pass
|
||||
`return_notifications?: true`. If you are in a changeset hook, you can simply
|
||||
`return_notifications?: true`. If you are in a changeset hook, you can
|
||||
return the notifications. If not, you can send the notifications using
|
||||
`Ash.Notifier.notify/1` once your resources are out of a transaction.
|
||||
"""
|
||||
|
@ -203,7 +203,7 @@ defmodule Ash.Actions.Helpers do
|
|||
Missed #{Enum.count(missed)} notifications in action #{inspect(resource)}.#{action.name}.
|
||||
|
||||
This happens when the resources are in a transaction, and you did not pass
|
||||
`return_notifications?: true`. If you are in a changeset hook, you can simply
|
||||
`return_notifications?: true`. If you are in a changeset hook, you can
|
||||
return the notifications. If not, you can send the notifications using
|
||||
`Ash.Notifier.notify/1` once your resources are out of a transaction.
|
||||
|
||||
|
|
|
@ -215,9 +215,9 @@ defmodule Ash.Changeset do
|
|||
of the relationship.
|
||||
|
||||
Datalayers currently are not notified of the `select` for a changeset(unlike queries), and creates/updates select all fields when they are performed.
|
||||
A select provided on a changeset simply sets the unselected fields to `nil` before returning the result.
|
||||
A select provided on a changeset sets the unselected fields to `nil` before returning the result.
|
||||
|
||||
Use `ensure_selected/2` if you simply wish to make sure a field has been selected, without deselecting any other fields.
|
||||
Use `ensure_selected/2` if you wish to make sure a field has been selected, without deselecting any other fields.
|
||||
"""
|
||||
def select(changeset, fields, opts \\ []) do
|
||||
if opts[:replace?] do
|
||||
|
@ -287,7 +287,7 @@ defmodule Ash.Changeset do
|
|||
@doc """
|
||||
Constructs a changeset for a given action, and validates it.
|
||||
|
||||
Simply calls `for_create/4`, `for_update/4` or `for_destroy/4` based on the type of action passed in.
|
||||
Calls `for_create/4`, `for_update/4` or `for_destroy/4` based on the type of action passed in.
|
||||
|
||||
See those functions for more explanation.
|
||||
"""
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
defmodule Ash.DataLayer.Simple do
|
||||
@moduledoc """
|
||||
A data layer that simply returns structs
|
||||
A data layer that returns structs.
|
||||
|
||||
This is the data layer that is used under the hood
|
||||
by embedded resources, and resources without data layers.
|
||||
|
|
|
@ -18,7 +18,7 @@ defmodule Ash.Engine do
|
|||
designed to be configurable. What exactly is done, as well as the order it is done in,
|
||||
and whether or not is can be parallelized, varies wildly based on factors like how
|
||||
the resources are configured and what capabilities the data layer has. By implementing
|
||||
a generic "parallel engine", we can let the engine solve that problem. We simply
|
||||
a generic "parallel engine", we can let the engine solve that problem. We only
|
||||
have to express the various operations that must happen, and what other pieces of data
|
||||
they need in order to happen, and the engine handles the rest.
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ defmodule Ash.Error.Forbidden.Policy do
|
|||
@help_text """
|
||||
|
||||
A check status of `?` implies that the solver did not need to determine that check.
|
||||
Some checks may look like they failed when in reality there was simply no need to check them.
|
||||
Some checks may look like they failed when in reality there was no need to check them.
|
||||
Look for policies with `✘` and `✓` in check statuses.
|
||||
|
||||
A check with a `⬇` means that it didn't determine if the policy was authorized or forbidden, and so moved on to the next check.
|
||||
|
|
|
@ -69,10 +69,6 @@ defmodule Ash.Filter do
|
|||
@moduledoc """
|
||||
The representation of a filter in Ash.
|
||||
|
||||
Ash filters are stored as nested `Ash.Query.BooleanExpression{}` and `%Ash.Query.Not{}` structs,
|
||||
terminating in an operator or a function struct. An expression is simply a boolean operator
|
||||
and the left and right hand side of that operator.
|
||||
|
||||
## Filter Templates
|
||||
|
||||
To see the available templates, see `Ash.Filter.TemplateHelpers`.
|
||||
|
|
|
@ -99,8 +99,8 @@ defmodule Ash.Notifier.PubSub do
|
|||
doc: """
|
||||
A named pub sub to pass as the first argument to broadcast.
|
||||
|
||||
If you are simply using your `Endpoint` module for pubsub then this is unnecessary. If you want to use
|
||||
a custom pub started with something like `{Phoenix.PubSub, name: MyName}`, then you can provide `MyName` to
|
||||
If you are using a phoenix `Endpoint` module for pubsub then this is unnecessary. If you want to use
|
||||
a custom pub sub started with something like `{Phoenix.PubSub, name: MyName}`, then you can provide `MyName` to
|
||||
here.
|
||||
""",
|
||||
links: []
|
||||
|
|
|
@ -3,9 +3,9 @@ defmodule Ash.Policy.Check do
|
|||
A behaviour for declaring checks, which can be used to easily construct
|
||||
authorization rules.
|
||||
|
||||
If a check can be expressed simply as a function of the actor, or the context of the request,
|
||||
If a check can be expressed simply, i.e as a function of the actor, or the context of the request,
|
||||
see `Ash.Policy.SimpleCheck` for an easy way to write that check.
|
||||
If a check can be expressed simply with a filter statement, see `Ash.Policy.FilterCheck`
|
||||
If a check can be expressed with a filter statement, see `Ash.Policy.FilterCheck`
|
||||
for an easy way to write that check.
|
||||
"""
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ defmodule Ash.Policy.SimpleCheck do
|
|||
@moduledoc """
|
||||
A type of check that operates only on request context, never on the data
|
||||
|
||||
Simply define `c:match?/3`, which gets the actor, request context, and opts, and returns true or false
|
||||
Define `c:match?/3`, which gets the actor, request context, and opts, and returns true or false
|
||||
"""
|
||||
@type authorizer :: Ash.Policy.Authorizer.t()
|
||||
@type options :: Keyword.t()
|
||||
|
|
|
@ -518,7 +518,7 @@ defmodule Ash.Query do
|
|||
a relationship with a query, an error is produced if the query does not select the destination field
|
||||
of the relationship.
|
||||
|
||||
Use `ensure_selected/2` if you simply wish to make sure a field has been selected, without deselecting any other fields.
|
||||
Use `ensure_selected/2` if you wish to make sure a field has been selected, without deselecting any other fields.
|
||||
"""
|
||||
def select(query, fields, opts \\ []) do
|
||||
query = to_query(query)
|
||||
|
|
|
@ -67,7 +67,7 @@ defmodule Ash.Resource.Change.Builtins do
|
|||
@doc """
|
||||
Clears a change off of the changeset before the action runs.
|
||||
|
||||
Does not fail if it is being changed, simply ensures it is cleared just before the action.
|
||||
Does not fail if it is being changed, but ensures it is cleared just before the action.
|
||||
|
||||
Can be useful if a change is only used in validations but shouldn't ultimately be written to the data layer.
|
||||
|
||||
|
@ -141,9 +141,9 @@ defmodule Ash.Resource.Change.Builtins do
|
|||
Keep in mind, this will *limit* the fields that are selected. You may want `ensure_selected/1` if you
|
||||
want to make sure that something is selected, without deselecting anything else.
|
||||
|
||||
Selecting in changesets does not actually do a select in the data layer, it simply nils out any
|
||||
fields that were not selected. This can be useful if you are writing policies that have to do with
|
||||
specific fields being selected.
|
||||
Selecting in changesets does not actually do a select in the data layer. It nils out any
|
||||
fields that were not selected after completing the action. This can be useful if you are writing
|
||||
policies that have to do with specific fields being selected.
|
||||
|
||||
## Example
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@ defmodule Ash.Resource.Change do
|
|||
@moduledoc """
|
||||
The behaviour for an action-specific resource change.
|
||||
|
||||
To implement one, simply implement the behaviour. `c:init/1` is defined automatically
|
||||
by `use Ash.Resource.Change`, but can be implemented if you want to validate/transform any
|
||||
`c:init/1` is defined automatically by `use Ash.Resource.Change`, but can be implemented if you want to validate/transform any
|
||||
options passed to the module.
|
||||
|
||||
The main function is `c:change/3`. It takes the changeset, any options that were provided
|
||||
|
|
|
@ -991,7 +991,7 @@ defmodule Ash.Resource.Dsl do
|
|||
describe: """
|
||||
Declares a named `list` aggregate on the resource.
|
||||
|
||||
A list aggregate simply selects the list of all values for the given field
|
||||
A list aggregate selects the list of all values for the given field
|
||||
and relationship combination.
|
||||
""",
|
||||
examples: [
|
||||
|
|
|
@ -2,8 +2,7 @@ defmodule Ash.Resource.Preparation do
|
|||
@moduledoc """
|
||||
The behaviour for an action-specific query preparation.
|
||||
|
||||
To implement one, simply implement the behaviour. `c:init/1` is defined automatically
|
||||
by `use Ash.Resource.Preparation`, but can be implemented if you want to validate/transform any
|
||||
`c:init/1` is defined automatically by `use Ash.Resource.Preparation`, but can be implemented if you want to validate/transform any
|
||||
options passed to the module.
|
||||
|
||||
The main function is `c:prepare/3`. It takes the changeset, any options that were provided
|
||||
|
|
|
@ -17,7 +17,7 @@ defmodule Ash.Seed do
|
|||
Any `nil` values will be overwritten with their default values. To avoid this, either use `seed/2`
|
||||
in which providing the key will have it not set the default values.
|
||||
If you want to force `nil` to be accepted and prevent the default value from being set, use the
|
||||
`keep_nil/0` function provided here, which simply returns `:__keep_nil__`. Alternatively, use
|
||||
`keep_nil/0` function provided here, which returns `:__keep_nil__`. Alternatively, use
|
||||
`seed!(Post, %{text: nil})`.
|
||||
|
||||
See `seed!/2` for more information.
|
||||
|
|
Loading…
Reference in a new issue