https://hexdocs.pm/ash/get-started.html 를 따라가며 Ash 프레임워크를 살펴 본다. 이전 글에 이어서 Ticket 리소스를 업데이트 하는 방법을 알아 본다.
Ticket 을 종료하는 기능이 필요하다. 티켓이 가지고 있는 status 를 :closed 로 바꾸면 된다. 이미 :closed status 인 경우 값을 변경하지 않고 적절한 에러 메시지를 안내한다.
Ticket 리소스에서 다음과 같이 선언을 변경한다.
# lib/helpdesk/support/ticket.ex
actions do
...
update :close do
accept []
validate attribute_does_not_equal(:status, :closed) do
message "Ticket is already closed"
end
change set_attribute(:status, :closed)
end
end
액션의 형태는 update 이고 이름은 :close 이다. 파라미터가 필요하다면 accept 를 줄 수 있다. 이 예제는 티켓을 종료할 때 특별히 전달 받을 데이터가 없으므로 빈 리스트로 지정한다.
validate 는 값의 유효성을 검사하기 위해 사용한다. 그대로 읽어 보자면 :status attribute_does_not_equal :closed -> :status 속성은 :closed 가 아니어야 한다 로 읽을 수 있을 것 같다. 따라오는 do ~ end 는 이 조건에 해당하지 않으면(즉, invalidate 하다면) 처리할 내용이다. attribute_does_not_equal 은 Built-in function 이다. https://hexdocs.pm/ash/validations.html 페이지에 사용할 수 있는 validation built-in function 목록이 있다. custom validation function 도 만들 수 있다.
change 는 값을 변경할 때 사용한다. 예제 코드는 :status attribute 를 :closed 로 변경한다. validate 와 마찬가지로 Built-in function 들이 준비되어 있고 custom change function 도 만들 수 있다.
다음은 실행 결과이다.
% iex -S mix
iex(1)> ticket = Helpdesk.Support.Ticket |> Ash.Changeset.for_create(:open, %{subject: "My mouse won't click!"}) |> Ash.create!()
%Helpdesk.Support.Ticket{
id: "054e9700-03e4-4ec4-8b6b-7964a258e775",
subject: "My mouse won't click!",
status: :open,
__meta__: #Ecto.Schema.Metadata<:built, "">
}
iex(2)> ticket = ticket |> Ash.Changeset.for_update(:close) |> Ash.update!()
%Helpdesk.Support.Ticket{
id: "054e9700-03e4-4ec4-8b6b-7964a258e775",
subject: "My mouse won't click!",
status: :closed,
__meta__: #Ecto.Schema.Metadata<:built, "">
}
iex(3)> ticket |> Ash.Changeset.for_update(:close) |> Ash.update!()
** (Ash.Error.Invalid)
Invalid Error
* Invalid value provided for status: Ticket is already closed.
Value: :closed
update 액션이기 때문에 Ash.Changeset.for_update(:close) 로 호출했다. 이어지는 함수 호출도 create!() 가 아닌 Ash.update!() 이다. 이미 :closed 로 변경된 ticket 을 다시 :close 액션을 호출하는 경우 에러가 발생하는 것을 확인할 수 있다.
다음 글 에서는 리소스를 조회하는 방법에 대해 알아보겠다.

댓글을 달려면 로그인해야 합니다.