Ash Framework 튜토리얼 따라하기 (4)

지난 글에 이어서 Ash 프레임워크에서 데이터를 쿼리하는 방법을 알아본다.

먼저 Ticket 리소스 전체 목록을 가져오는 코드는 다음과 같다.

Ash.read!(Helpdesk.Support.Ticket)

그러나 지금 상황에서 코드를 바로 실행하면 다음과 같은 오류가 발생한다.

iex> Ash.read!(Helpdesk.Support.Ticket)
** (Ash.Error.Framework) 
Bread Crumbs:
  > Error returned from: Helpdesk.Support.Ticket.read

Framework Error

* No data provided to resource Elixir.Helpdesk.Support.Ticket. Perhaps you are missing a call to `Ash.DataLayer.Simple.set_data/2`?.

Another common cause of this is failing to add a data layer for a resource. You can add a data layer like so:

`use Ash.Resource, data_layer: Ash.DataLayer.Ets`

Ticket 리소스에 대해 데이터 레이어가 없다는 얘기다. 지금까지 리소스를 정의만 했지 어디에 저장할지는 정의하지 않았다. 리소스를 어디에 저장할 지 데이터 레이어를 지정하면 해결되지만 그 전에 데이터 레이어가 없는 경우에는 어떻게 다룰 수 있는지 알아 보자.

데이터 레이어가 없는 리소스는 암시적으로 Ash.DataLayer.Simple 를 사용한다. 이 데이터는 어디에도 영속화 되지 않으며 쿼리가 실행될 때 같이 제공되어야 한다.

조회를 시험해 볼 데이터를 먼저 만든다.

iex> tickets =
  for i <- 0..5 do
    ticket =
      Helpdesk.Support.Ticket
      |> Ash.Changeset.for_create(:open, %{subject: "Issue #{i}"})
      |> Ash.create!()

    if rem(i, 2) == 0 do
      ticket
      |> Ash.Changeset.for_update(:close)
      |> Ash.update!()
    else
      ticket
    end
  end

[
  %Helpdesk.Support.Ticket{
    id: "d2c428d4-d3c6-474a-a353-3ecdaeef3080",
    subject: "Issue 0",
    status: :closed,
    __meta__: #Ecto.Schema.Metadata<:built, "">
  },
  %Helpdesk.Support.Ticket{
    id: "34844252-aeeb-4c4f-9d1b-9526f9ac9813",
    subject: "Issue 1",
    status: :open,
    __meta__: #Ecto.Schema.Metadata<:built, "">
  },
  %Helpdesk.Support.Ticket{
    id: "4dd6b7b4-a3c5-4630-b26f-d85550b53858",
    subject: "Issue 2",
    status: :closed,
    __meta__: #Ecto.Schema.Metadata<:built, "">
  },
  %Helpdesk.Support.Ticket{
    id: "6def5674-8504-4062-a1d6-b5cc1c2c1b06",
    subject: "Issue 3",
    status: :open,
    __meta__: #Ecto.Schema.Metadata<:built, "">
  },
  %Helpdesk.Support.Ticket{
    id: "edc86cc1-0455-41ab-8f6e-2d3b00351bb5",
    subject: "Issue 4",
    status: :closed,
    __meta__: #Ecto.Schema.Metadata<:built, "">
  },
  %Helpdesk.Support.Ticket{
    id: "e537457b-59fa-4d41-bf6f-54ac019ed76c",
    subject: "Issue 5",
    status: :open,
    __meta__: #Ecto.Schema.Metadata<:built, "">
  }
]

tickets 에 임의의 리소스 목록이 만들어 졌다. 영속화 되지 않은 데이터이다. 이 데이터를 Ash 를 통해 조회하려면 어떻게 할 수 있는지 알아 보자. 제목에 “2” 를 포함한 리소스만 읽는 쿼리는 다음과 같다.


# Ash.Query는 매크로이므로 require 해야 함
iex> require Ash.Query 

Ash.Query

iex> Helpdesk.Support.Ticket |> Ash.Query.filter(contains(subject, "2")) |> Ash.DataLayer.Simple.set_data(tickets) |> Ash.read!()

[
  %Helpdesk.Support.Ticket{
    id: "4dd6b7b4-a3c5-4630-b26f-d85550b53858",
    subject: "Issue 2",
    status: :closed,
    __meta__: #Ecto.Schema.Metadata<:built, "">
  }
]

Ash.read!() 전에 Ash.DataLayer.Simple.set_data(tickets) 를 통해 파이프라인에 tickets 데이터를 제공한 것을 확인할 수 있다. Ash.Query.filter(contains(subject, "2")) 는 일종의 where 절 이라고 볼 수 있다. 예제 코드의 순서는 read 직전에 set_data 를 지정했지만 set_data 부터 하고 이후에 filter 를 해도 결과는 같았다.

다음은 :closed 티켓 중 제목에 “4” 가 포함되지 않은 티켓의 목록을 얻는 코드이다.

Helpdesk.Support.Ticket
|> Ash.Query.filter(status == :closed and not(contains(subject, "4")))
|> Ash.DataLayer.Simple.set_data(tickets)
|> Ash.read!()

다음 글 에서는 데이터 영속화에 대해 알아 본다.

댓글 남기기