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)
The Ticket resource will represent a helpdesk ticket.
It will have 3 main attributes.
- A
subject
or title - A
description
- A
status
which can be either:open
or:closed
It will also have 2 attributes for keeping track of when the ticket was created, and when it was last updated.
You need to make sure the subject
is always set, it's not possible to create a ticket without a subject. You can do this by setting allow_nil?
to false
. Like so: attribute :subject, :string, allow_nil?: false
The :description
is simple, it's a :string
and it is allowed to be empty.
:status
is more complicated.
- It is of the type
:atom
- It can only be the value
:open
or:closed
- By default it is
:open
- And it can't be
nil
Attributes are set in a do end
block like so:
attribute :status, :atom do
# ...
allow_nil? false
end
To set a constraint of values, you can use the constraints
option, like so:
constraints [one_of: [:open, :closed]]
To set the default value, you use default :open
.
Ash provides create_timestamp and update_timestamp to keep track of when the Resource was first created, and when it was last updated.
Add the following to the attributes block:
create_timestamp :created_at
update_timestamp :updated_at
Show 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]
end
end
attributes do
uuid_primary_key :id
attribute :subject, :string, allow_nil?: false
attribute :description, :string
# status is either `open` or `closed`.
attribute :status, :atom do
# Constraints allow you to provide extra rules for the value.
# The available constraints depend on the type
# See the documentation for each type to know what constraints are available
# Since atoms are generally only used when we know all of the values
# it provides a `one_of` constraint, that only allows those values
constraints [one_of: [:open, :closed]]
default :open
allow_nil? false
end
create_timestamp :created_at
update_timestamp :updated_at
end
end
defmodule Tutorial.Support do
use Ash.Domain
resources do
resource Tutorial.Support.Ticket
end
end
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
# Add the attributes here -->
# - Subject
# - Description
# - Status
# - Create Timestamp
# - Update Timestamp
end
end
defmodule Tutorial.Support do
use Ash.Domain
resources do
resource Tutorial.Support.Ticket
end
end
Create a Ticket
without any attributes.
Remember, when creating a resource use a changeset (Ash.Changeset.for_create/3
), which gets passed to Ash.create!/1
.
The output should look something like this:
** (Ash.Error.Invalid) Input Invalid
* attribute subject is required
Show Solution
Tutorial.Support.Ticket
|> Ash.Changeset.for_create(:create, %{})
|> Ash.create!()
Now create a Ticket with a subject
Show Solution
Tutorial.Support.Ticket
|> Ash.Changeset.for_create(:create, %{subject: "This is the subject"})
|> Ash.create!()
Now create a ticket with the status
set to :closed
Show Solution
Tutorial.Support.Ticket
|> Ash.Changeset.for_create(:create, %{subject: "This is the subject", status: :closed})
|> Ash.create!()
Now try creating a ticket with the status set to :pending
. This should give an error because :pending
is not a valid status
.
Show Solution
Tutorial.Support.Ticket
|> Ash.Changeset.for_create(:create, %{subject: "This is the subject", status: :pending})
|> Ash.create!()
Since you added a creation date, you can now query on the latest created ticket.
First, sort using the Ash.Query.sort/2
function by Ash.Query.sort(created_at: :desc)
Then limit the amount of records with the Ash.Query.limit/2
function by doing Ash.Query.limit(1)
Finally call Ash.read_one!()
on the query.
Hint: Use a pipeline
Show Solution
Tutorial.Support.Ticket
|> Ash.Query.sort(created_at: :desc)
|> Ash.Query.limit(1)
|> Ash.read_one!()