Ash: 8 - Relationships
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
Customizing Actions HomeCode InterfacesIn 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
Show Solution
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
# ...
Enter your solution
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, :representative_id]
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
relationships do
belongs_to :representative, Tutorial.Support.Representative
end
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
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.
# 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.
# 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.