Search code examples
elixirphoenix-framework

How to prevent nil values in Ecto Changeset?


I have an update_changeset in which I want to prevent nil values from being written.

I tried adding a validate_change

 def update_changeset(user, attrs) do
    user
    |> cast(attrs, [:full_name])
    |> validate_change(:full_name, fn :full_name, full_name ->
      if full_name == nil do
        [full_name: "cannot be blank"]
      else
        []
      end
    end)
  end

But since it only gets called when a non-nil value is present, it still lets me write full_name: nil into the database.

How can I make this work?

Updated: here is how I implemented from help from fellows:

defp prevent_empty(changeset, fields) do
    Enum.reduce(fields, changeset, fn field, changeset ->
      value = get_field(changeset, field)

      if value in ["", nil] do
        add_error(changeset, field, "cannot be empty or blank")
      else
        changeset
      end
    end)
  end

Solution

  • One has to handle it manually, with a help of Ecto.Changeset.add_error/4.

    def update_changeset(user, %{full_name: fn} = attrs) do
      user
      |> cast(attrs, [:full_name])
      |> prevent_empty_full_name()
    end
    
    defp prevent_empty_full_name(%{changes: %{full_name: full_name}} = changeset)
        when full_name in ["", nil],
      do: add_error(changeset, :full_name, "empty")
    
    defp prevent_empty_full_name(changeset),
      do: changeset