Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Ash: 3 - Querying

ash_tutorial/querying.livemd

Ash: 3 - Querying

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)

But First, Data Persistence

Actions HomeAttributes

So far we have just created changesets, but we have not actually created any instances of a resource, also known as records. Before we can play around with querying, we need to add a data layer. It is much more common to use Postgres in production, but we will use ETS data layer for the remainder of this tutorial to keep dependencies to a minimum.

 use Ash.Resource,
      domain: YourDomain,
      data_layer: Ash.DataLayer.Ets

In this tutorial you will do basic Query and CRUD operations

But first you need to enable all basic CRUD operations.

Do this by adding default :read and :destroy actions, as well as :create and :update actions that accept [:name].

Show Solution

  defmodule Tutorial.Profile do
    use Ash.Resource,
      domain: Tutorial,
      data_layer: Ash.DataLayer.Ets

    actions do
      defaults [:read, :destroy]

      create :create do
        accept [:name]
      end

      update :update do
        accept [:name]
      end
    end

    attributes do
      uuid_primary_key :id
      attribute :name, :string
    end
  end

  defmodule Tutorial do
    use Ash.Domain

    resources do
      resource Tutorial.Profile
    end
  end

Enter your solution

defmodule Tutorial.Profile do
  use Ash.Resource,
    domain: Tutorial,
    data_layer: Ash.DataLayer.Ets

  actions do
    defaults [:read, :destroy]
    
    create :create do
      accept [:name]
    end
    
    update :update do
      accept [:name]
    end
  end

  attributes do
    uuid_primary_key :id
    attribute :name, :string
  end
end

defmodule Tutorial do
  use Ash.Domain

  resources do
    resource Tutorial.Profile
  end
end

Creating

Add 2 Profiles to the database.

  • One with the name “Joe Armstrong”
  • One with your name

You can create a Profile by:

  • Creating a Changeset with Ash.Changeset.for_create(Tutorial.Profile, :create, %{name: "Your Name"}),
  • Then giving the changeset to Ash.create!().

Hint: Use a pipeline

Show Solution

  Tutorial.Profile
  |> Ash.Changeset.for_create(:create, %{name: "The Name"})
  |> Ash.create!()

Enter your solution

Tutorial.Profile
|> Ash.Changeset.for_create(:create, %{name: "Joe Armstrong"})
|> Ash.create!()

Tutorial.Profile
|> Ash.Changeset.for_create(:create, %{name: "My name"})
|> Ash.create!()

Reading

Now, read all the generated Profiles.

Call Ash.read!/1 with the Tutorial.Profile module.

Show Solution

  Tutorial.Profile
  |> Ash.read!()

Enter your solution

Tutorial.Profile
|> Ash.read!()

Now fetch the “Joe Armstrong” Profile.

You can achieve this by introducing a filter.

First you’ll need to require Ash.Query

Then call Ash.Query.filter(name == "Joe Armstrong") with the Tutorial.Profile.

Put the result into the joe variable. Ash.read!/1 returns a list, so make sure to extract the single returned value out of that list.

Show Solution

  require Ash.Query

  [joe] =
    Tutorial.Profile
    |> Ash.Query.filter(name == "Joe Armstrong")
    |> Ash.read!()

Enter your solution

require Ash.Query

[joe] =
  Tutorial.Profile
  |> Ash.Query.filter(name == "Joe Armstrong")
  |> Ash.Query.limit(1)
  |> Ash.read!()

You’ll use the joe variable in the next sections.

Updating

Now change Joe Armstrong‘s name to Neil Armstrong.

You can do this by providing the Ash.Changeset.for_update/3 with:

  • the resource you want to change, in this case joe
  • the :update atom
  • a map of the values you want to change, in this case %{name: "Neil Armstrong"}

Then apply the changeset by calling Ash.update!/1 with the changeset.

Hint: Using a pipeline might be a good idea.

Show Solution

  joe
  |> Ash.Changeset.for_update(:update, %{name: "Neil Armstrong"})
  |> Ash.update!()

Enter your solution

joe
|> Ash.Changeset.for_update(:update, %{name: "Neil Armstrong"})
|> Ash.update!()

Destroying

Finally, remove joe from the database.

Do this using the Ash.destroy!/1 function.

Show Solution

  Ash.destroy!(joe)

Enter your solution

joe
|> Ash.destroy!()
Actions HomeAttributes