유효성 검사를 위한 간단한 Elixir 상태 머신

8042 단어 elixir
어느 시점에서 우리는 상태가 많은 가능성으로 전환될 수 있는 엔터티를 갖게 될 것이며 데이터의 무결성을 적용하는 규칙을 원합니다.

예를 들어 이것은 인간의 감정 상태 변화 다이어그램입니다.



일부 전환은 괜찮지만 일부 전환은 그렇지 않습니다.

# 👌 OK
iex> update(%Human{emotion: :hungry}, %{emotion: :full})
{:ok, %Human{emotion: :full}}

# 🙅‍♂️ No, get something to eat first!
iex> update(%Human{emotion: :hungry}, %{emotion: :sleepy})
{:error, "invalid status change"}


🤖 패턴 매칭으로 간단한 검증



엘릭서 개발자 입장에서는 패턴매칭이 이와 같은 상태 변화 문제를 해결하는데 상당히 좋은 방법이라고 짐작할 수 있습니다.

def update(%Human{} = human, attrs) do
  with :ok <- validate_status(human.emotion, attrs.emotion),
  ...
end



def validate_status(current_status, new_status) do
  case {current_status, new_status} do
    # Put all the transition paths as a whitelist
    {:hungry, :full} -> :ok
    {:hungry, :angry} -> :ok
    {:angry, :angry} -> :ok
    {:angry, :full} -> :ok
    {:full, :sleepy} -> :ok

    # return error for the rest
    _ -> {:error, "invalid status change"}
  end
end


⚡️ 이 규칙을 Ecto 변경 집합에 포함할 수 있습니까?



규칙을 ecto 데이터 스키마에 엄격하게 적용하려는 경우 상태 변경에 대한 사용자 지정 변경 세트 유효성 검사도 구축할 수 있습니다.

def changeset(human, attrs \\ %{}) do
  human
  |> cast(...)
  |> validate_required(...)
  |> validate_status_change() # <- custom validation
end



def validate_status_change(changeset) do
  # Get current and new field data
  current_status = changeset.data.status
  new_status = get_field(changeset, :status)

  case {current_status, new_status} do
    # do nothing if ok
    {:hungry, :full} -> changeset
    {:hungry, :angry} -> changeset
    {:angry, :angry} -> changeset
    {:angry, :full} -> changeset
    {:full, :sleepy} -> changeset
    {nil, _} -> changeset # any new status is ok

    # add error to ecto changeset errors
    _ -> add_error(changeset, :status, "invalid status change")
  end
end


그게 다야! 이것이 다음 작업에 대한 아이디어를 줄 수 있기를 바랍니다. 의견이 있으시면 자유롭게 토론하십시오! 😊

좋은 웹페이지 즐겨찾기