164 lines
4.4 KiB
Markdown
164 lines
4.4 KiB
Markdown
# Ash: 6 - Relationships
|
|
|
|
```elixir
|
|
Application.put_env(:ash, :validate_domain_resource_inclusion?, false)
|
|
Application.put_env(:ash, :validate_domain_config_inclusion?, false)
|
|
Mix.install([{:ash, "~> 3.0"}], consolidate_protocols: false)
|
|
```
|
|
|
|
## Relationships
|
|
|
|
<div class="flex items-center w-full flex-start justify-between rounded-xl p-4" style="background-color: #f0f5f9; color: #61758a;">
|
|
<div class="flex">
|
|
<i class="ri-arrow-left-fill"></i>
|
|
<a class="flex ml-2" style="color: #61758a;" href="customizing_actions.livemd">Customizing Actions</a>
|
|
</div>
|
|
<div class="flex">
|
|
<i class="ri-home-fill"></i>
|
|
<a class="flex ml-2" style="color: #61758a;" href="overview.livemd">Home</a>
|
|
</div>
|
|
<div class="flex">
|
|
<a class="flex mr-2" style="color: #61758a;" href="code_interfaces.livemd">Code Interfaces</a>
|
|
<i class="ri-arrow-right-fill"></i>
|
|
</div>
|
|
</div>
|
|
|
|
### In this tutorial you will create a relationship between a Ticket and Representative resource
|
|
|
|
Create a `relationships do .. end` block in the Ticket resource.
|
|
|
|
Inside the `relationships` block, define a `belongs_to` representative like so:
|
|
|
|
`belongs_to :representative, Tutorial.Support.Representative`
|
|
|
|
<details class="rounded-lg my-4" style="background-color: #96ef86; color: #040604;">
|
|
<summary class="cursor-pointer font-bold p-4"></i>Show Solution</summary>
|
|
<div class="p-4">
|
|
|
|
```elixir
|
|
defmodule Tutorial.Support.Ticket do
|
|
|
|
# ...
|
|
|
|
relationships do
|
|
# belongs_to means that the destination attribute is unique, meaning only one related record could exist.
|
|
# We assume that the destination attribute is `representative_id` based
|
|
# on the name of this relationship and that the source attribute is `representative_id`.
|
|
# We create `representative_id` automatically.
|
|
belongs_to :representative, Tutorial.Support.Representative
|
|
end
|
|
|
|
# ...
|
|
```
|
|
|
|
</div>
|
|
</details>
|
|
|
|
### Enter your solution
|
|
|
|
```elixir
|
|
defmodule Tutorial.Support.Ticket do
|
|
use Ash.Resource,
|
|
domain: Tutorial.Support,
|
|
data_layer: Ash.DataLayer.Ets
|
|
|
|
actions do
|
|
defaults [:read]
|
|
|
|
create :create do
|
|
accept [:subject, :description, :status]
|
|
end
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key :id
|
|
attribute :subject, :string, allow_nil?: false
|
|
attribute :description, :string
|
|
|
|
attribute :status, :atom do
|
|
constraints one_of: [:open, :closed]
|
|
default :open
|
|
allow_nil? false
|
|
end
|
|
|
|
create_timestamp :created_at
|
|
update_timestamp :updated_at
|
|
end
|
|
|
|
# <-- Add the relationship here
|
|
end
|
|
|
|
defmodule Tutorial.Support.Representative do
|
|
use Ash.Resource,
|
|
domain: Tutorial.Support,
|
|
data_layer: Ash.DataLayer.Ets
|
|
|
|
actions do
|
|
defaults [:read]
|
|
|
|
create :create do
|
|
accept [:name]
|
|
end
|
|
end
|
|
|
|
attributes do
|
|
uuid_primary_key(:id)
|
|
attribute(:name, :string)
|
|
end
|
|
end
|
|
```
|
|
|
|
```elixir
|
|
defmodule Tutorial.Support do
|
|
use Ash.Domain
|
|
|
|
resources do
|
|
resource Tutorial.Support.Ticket
|
|
resource Tutorial.Support.Representative
|
|
end
|
|
end
|
|
```
|
|
|
|
## Creating a Ticket record with a representative Relationship
|
|
|
|
First, create the representative Joe.
|
|
|
|
```elixir
|
|
# Creates a Representative
|
|
joe =
|
|
Tutorial.Support.Representative
|
|
|> Ash.Changeset.for_create(:create, %{name: "Joe Armstrong"})
|
|
|> Ash.create!()
|
|
```
|
|
|
|
Next up, create a ticket and assign the representative Joe to the ticket.
|
|
|
|
```elixir
|
|
# Creates a Ticket with the representative
|
|
Tutorial.Support.Ticket
|
|
|> Ash.Changeset.for_create(:create, %{subject: "My spoon is too big!", representative_id: joe.id})
|
|
|> Ash.create!()
|
|
# `load!/2` loads in the representative. Try removing this line to see what changes
|
|
|> Ash.load!([:representative])
|
|
```
|
|
|
|
As you can see it didn't quite work. The `representative_id` is not accepted by the create action on `Tutorial.Support.Ticket`. If you add `:representative_id` to that list,
|
|
and try again you should now see that the representative was correctly assigned.
|
|
|
|
<!-- livebook:{"break_markdown":true} -->
|
|
|
|
<div class="flex items-center w-full flex-start justify-between rounded-xl p-4" style="background-color: #f0f5f9; color: #61758a;">
|
|
<div class="flex">
|
|
<i class="ri-arrow-left-fill"></i>
|
|
<a class="flex ml-2" style="color: #61758a;" href="customizing_actions.livemd">Customizing Actions</a>
|
|
</div>
|
|
<div class="flex">
|
|
<i class="ri-home-fill"></i>
|
|
<a class="flex ml-2" style="color: #61758a;" href="overview.livemd">Home</a>
|
|
</div>
|
|
<div class="flex">
|
|
<a class="flex mr-2" style="color: #61758a;" href="code_interfaces.livemd">Code Interfaces</a>
|
|
<i class="ri-arrow-right-fill"></i>
|
|
</div>
|
|
</div>
|