mirror of
https://github.com/ash-project/ash.git
synced 2024-09-20 13:33:20 +12:00
improvement: update ash docs
This commit is contained in:
parent
696f7ca82a
commit
1ff91f303d
9 changed files with 104 additions and 27 deletions
|
@ -85,6 +85,22 @@ User
|
||||||
|
|
||||||
See the documentation for `Ash.Query.calculate/4` for more information.
|
See the documentation for `Ash.Query.calculate/4` for more information.
|
||||||
|
|
||||||
|
## Arguments in calculations
|
||||||
|
|
||||||
|
Using the above example with arguments, you can load a calculation with arguments like so:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
load(full_name: [separator: ","])
|
||||||
|
```
|
||||||
|
|
||||||
|
If the calculation uses an expression, you can also filter and sort on it like so:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
query
|
||||||
|
|> Ash.Query.filter(full_name(separator: ","))
|
||||||
|
|> Ash.Query.sort(full_name: {:asc, %{separator: ","}})
|
||||||
|
```
|
||||||
|
|
||||||
## Async loading
|
## Async loading
|
||||||
|
|
||||||
Expensive calculations can be marked as `allow_async?: true`, which will allow Ash to fetch it after the main query is run, in parallel with any other calculations that are being run async. This won't affect calculations that are being filtered on, since that must be placed in the data layer.
|
Expensive calculations can be marked as `allow_async?: true`, which will allow Ash to fetch it after the main query is run, in parallel with any other calculations that are being run async. This won't affect calculations that are being filtered on, since that must be placed in the data layer.
|
|
@ -0,0 +1,70 @@
|
||||||
|
# Relationships
|
||||||
|
|
||||||
|
Relationships are a core component of Ash. They provide a mechanism to describe the relationships between your resources, and through those relationships you can do things like
|
||||||
|
|
||||||
|
- Loading related data
|
||||||
|
- Filtering on related data
|
||||||
|
- Managing related records through changes on a single resource
|
||||||
|
- Authorizing based on the state of related data
|
||||||
|
|
||||||
|
## Managing related data
|
||||||
|
|
||||||
|
See {{link:ash:guide:Managing Relationships}} for more information.
|
||||||
|
|
||||||
|
## Loading related data
|
||||||
|
|
||||||
|
Loading relationships is a very common use case. There are two ways to load relationships, in the query, and on records.
|
||||||
|
|
||||||
|
### On records
|
||||||
|
|
||||||
|
Given a set of records, like `[user1, user2]`, you can load their relationships by calling your Ash Api's `load` function.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
YourApi.load(users, :friends)
|
||||||
|
```
|
||||||
|
|
||||||
|
This will fetch the friends of each user, and set them in the corresponding `friends` key.
|
||||||
|
|
||||||
|
### In the query
|
||||||
|
|
||||||
|
Loading in the query is currently pretty much the same as loading on records, but eventually data layers will be able to optimize these loads, potentially including them as joins in the main query, for example. The following will return the list of users with their friends loaded, as the above example.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
User
|
||||||
|
|> Ash.Query.load(:friends)
|
||||||
|
|> YourApi.read()
|
||||||
|
```
|
||||||
|
|
||||||
|
## More complex data loading
|
||||||
|
|
||||||
|
Multiple relationships can be loaded at once, i.e
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
YourApi.load(users, [:friends, :enemies])
|
||||||
|
```
|
||||||
|
|
||||||
|
Nested relationships can be loaded:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
YourApi.load(users, friends: [:friends, :enemies])
|
||||||
|
```
|
||||||
|
|
||||||
|
The queries used for loading can be customized by providing a query as the value.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
friends = Ash.Query.sort(User, social_score: :asc)
|
||||||
|
|
||||||
|
YourApi.load(users, friends: friends)
|
||||||
|
```
|
||||||
|
|
||||||
|
Nested loads will be included in the parent load.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
friends =
|
||||||
|
User
|
||||||
|
|> Ash.Query.sort(social_score: :asc)
|
||||||
|
|> Ash.Query.load(:friends)
|
||||||
|
|
||||||
|
# Will load friends and friends of those friends
|
||||||
|
YourApi.load(users, friends: friends)
|
||||||
|
```
|
|
@ -1 +1,12 @@
|
||||||
|
# Testing
|
||||||
|
|
||||||
|
## Async tests
|
||||||
|
|
||||||
|
The first thing you will likely want to do, especially if you are using `AshPostgres`, is to add the following config to your `config/test.exs`.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# config/test.exs
|
||||||
config :ash, :disable_async?, true
|
config :ash, :disable_async?, true
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures that Ash does not spawn tasks when executing your requests, which is necessary for doing transactional tests with `AshPostgres`.
|
|
@ -26,22 +26,14 @@ defmodule Ash.Resource.Actions.SharedOptions do
|
||||||
|
|
||||||
Has no effect if the data layer does not support transactions, or if that data layer is already in a transaction.
|
Has no effect if the data layer does not support transactions, or if that data layer is already in a transaction.
|
||||||
""",
|
""",
|
||||||
links: [
|
links: []
|
||||||
guides: [
|
|
||||||
"ash:guide:Transactions"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
touches_resources: [
|
touches_resources: [
|
||||||
type: {:list, :atom},
|
type: {:list, :atom},
|
||||||
doc: """
|
doc: """
|
||||||
A list of resources that the action may touch, used when building transactions.
|
A list of resources that the action may touch, used when building transactions.
|
||||||
""",
|
""",
|
||||||
links: [
|
links: []
|
||||||
guides: [
|
|
||||||
"ash:guide:Transactions"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,7 @@ defmodule Ash.Resource.Dsl do
|
||||||
examples: [
|
examples: [
|
||||||
"create_timestamp :inserted_at"
|
"create_timestamp :inserted_at"
|
||||||
],
|
],
|
||||||
links: [
|
links: [],
|
||||||
guides: [
|
|
||||||
"ash:guide:Timestamps"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
target: Ash.Resource.Attribute,
|
target: Ash.Resource.Attribute,
|
||||||
args: [:name],
|
args: [:name],
|
||||||
schema: Ash.Resource.Attribute.create_timestamp_schema()
|
schema: Ash.Resource.Attribute.create_timestamp_schema()
|
||||||
|
@ -45,11 +41,7 @@ defmodule Ash.Resource.Dsl do
|
||||||
describe: """
|
describe: """
|
||||||
Declares a non-writable attribute with a create and update default of `&DateTime.utc_now/0`
|
Declares a non-writable attribute with a create and update default of `&DateTime.utc_now/0`
|
||||||
""",
|
""",
|
||||||
links: [
|
links: [],
|
||||||
guides: [
|
|
||||||
"ash:guide:Timestamps"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
examples: [
|
examples: [
|
||||||
"update_timestamp :inserted_at"
|
"update_timestamp :inserted_at"
|
||||||
],
|
],
|
||||||
|
@ -66,11 +58,7 @@ defmodule Ash.Resource.Dsl do
|
||||||
examples: [
|
examples: [
|
||||||
"timestamps()"
|
"timestamps()"
|
||||||
],
|
],
|
||||||
links: [
|
links: [ ],
|
||||||
guides: [
|
|
||||||
"ash:guide:Timestamps"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
target: Ash.Resource.Attribute,
|
target: Ash.Resource.Attribute,
|
||||||
auto_set_fields: [
|
auto_set_fields: [
|
||||||
name: :__timestamps__
|
name: :__timestamps__
|
||||||
|
@ -971,7 +959,7 @@ defmodule Ash.Resource.Dsl do
|
||||||
that matches. Supports both `filter` and `sort`.
|
that matches. Supports both `filter` and `sort`.
|
||||||
""",
|
""",
|
||||||
examples: [
|
examples: [
|
||||||
"""
|
""
|
||||||
first :first_assigned_ticket_subject, :assigned_tickets, :subject do
|
first :first_assigned_ticket_subject, :assigned_tickets, :subject do
|
||||||
filter [active: true]
|
filter [active: true]
|
||||||
sort [:subject]
|
sort [:subject]
|
||||||
|
|
Loading…
Reference in a new issue