I'm having a bit of trouble trying to implement a custom changeset validation. My schema is:
defenum(VersionStateEnum, ["draft", "active"])
schema "versions" do
field :expires_at, :utc_datetime
field :state, VersionStateEnum
end
The validation I'm trying to implement is: The expires_at can only be set if the state is draft (this should also be valid for updates, I should not be able to remove the expires_at if the state is still draft) I tried the following:
defp validate_expires_at(changeset) do
expires_at = get_change(changeset, :expires_at)
cond do
get_change(changeset, :state) == :draft ->
case expires_at do
nil -> add_error(changeset, :expires_at, "can't be blank when state is draft")
_ -> changeset
end
get_change(changeset, :state) == :active ->
case expires_at do
nil -> changeset
_ -> add_error(changeset, :expires_at, "cannot be set when state is not draft")
end
true ->
changeset
end
end
end
But it doesn't really work as I can update the expires_at to nil even if the state is draft. Any help is appreciated.
Edit 1: My changeset:
@required_fields [
:state
]
@optional_fields [:expires_at]
def changeset(model, params \\ nil) do
model
|> cast(params, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> validate_expires_at()
end
Where it's being called:
def create_document(attrs \\ %{}) do
%Document{}
|> Document.changeset(attrs)
|> Repo.insert()
end
stateas an atom or as a string?expires_ateven when it's a draft, so, can you please also include the code you're using to update it? And does it successfully insert if you just docreate_document(%{state: "draft"}), because I tried it and it did return an errored changeset