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

https://hexdocs.pm/ash/get-started.html 를 따라가며 Ash 프레임워크를 살펴 본다. 이전 글에 이어서 Ticket 리소스를 개선한다.

Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:create) |> Ash.create!() 를 통해 Ticket 데이터를 만들 수 는 있었지만 subject 를 입력할 수도 상태를 지정할 수 도 없었다. 보통 create 함수에 처음 세팅할 값을 전달하거나 create 함수 내부에서 기본 값을 설정하는 등 일정 로직이 필요하다.

먼저 Ticket 리소스의 attribute 들에 몇가지 속성을 추가하자.

# lib/helpdesk/support/ticket.ex

attributes do
  ...
  attribute :subject, :string do
    allow_nil? false

    public? true
  end

  attribute :status, :atom do
    constraints [one_of: [:open, :closed]]

    default :open

    allow_nil? false
  end
end

subject attribute에는 nil 을 허용하지 않는 속성이 추가되었고 public 속성이 이 true 가 되었다. 여기서 public/private 은 REST/GraphQL 등 외부 API로 노출되었을때에 대한 가시성을 의미한다. public 이면 나중에 API 로 접근할 경우 필드로 나타날 것이다. public? 으로 명시하지 않으면 기본적으로 모두 private 이다. 내부적 접근 (예를들어 subject = ticket.subject 같은) 과는 상관이 없다.

status attribute 가 추가되었고 자료형은 atom, 값에 대한 제약조건이 :open, :closed 중 한개로 제약 조건이 붙었다. 기본 값은 :open 이다.

attribute 를 보완했으니 create 액션도 보완할 차례다.

# lib/helpdesk/support/ticket.ex

actions do
  ...
  create :open do
    accept [:subject]
  end
end

create :create 에서 create :open 으로 변경되었다. create 액션의 이름이 :open 로 변경된 것이다. Ash.Changeset.for_create 호출 파라미터도 :open 으로 바뀌어야 한다. accept 은 값을 인자로 전달받을 attribute 를 지정한다. attribute 로 지정되어 있지 않은 이름을 atom 으로 작성하면 거절(컴파일 오류) 된다.

변경된 Ticket 리소스의 형태는 다음과 같다.

defmodule Helpdesk.Support.Ticket do
  use Ash.Resource, domain: Helpdesk.Support

  actions do
    defaults [:read]

    create :open do
      accept [:subject]
    end
  end

  attributes do
    uuid_primary_key :id

    attribute :subject, :string do
      allow_nil? false

      public? false
    end

    attribute :status, :atom do
      constraints one_of: [:open, :closed]

      default :open

      allow_nil? false
    end
  end
end

iex 를 재실행하거나 recompile() 해서 코드를 업데이트 하고 다음과 같이 값을 전달하여 Ticket을 만든다.

iex> recompile()

iex> Helpdesk.Support.Ticket
|> Ash.Changeset.for_create(:open, %{subject: "My mouse won't click!"})
|> Ash.create!()

%Helpdesk.Support.Ticket{
  id: "d29d5348-ff98-4cc2-adbd-bffe29cef64f",
  subject: "My mouse won't click!",
  status: :open,
  __meta__: #Ecto.Schema.Metadata<:built, "">
}

입력 값이 잘못되거나 액션 이름이 잘못되었다면 에러가 발생한다.

iex> ticket = Helpdesk.Support.Ticket|> Ash.Changeset.for_create(:open, %{subject1: "My mouse won't click!"})|> Ash.create!()
** (Ash.Error.Invalid) 
Bread Crumbs:
  > Error returned from: Helpdesk.Support.Ticket.open

Invalid Error

* No such input `subject1` for action Helpdesk.Support.Ticket.open

No such attribute on Helpdesk.Support.Ticket, or argument on Helpdesk.Support.Ticket.open

Did you mean:

* subject


Valid Inputs:

* subject
iex> ticket = Helpdesk.Support.Ticket|> Ash.Changeset.for_create(:open)|> Ash.create!()
** (Ash.Error.Invalid) 
Bread Crumbs:
  > Error returned from: Helpdesk.Support.Ticket.open

Invalid Error

* attribute subject is required

다음 글에서는 레코드의 변경과 검증에 대해 알아 보자.

댓글 남기기