Ecto.Changeset.cast/3 drops boolean values?

I have the following (slightly simplified) Ecto schema definition:

defmodule MyApp.Chunk do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary, []}
  @required [:id, :leaf, :payload]

  schema "chunks" do
    field :leaf, :boolean
    field :payload, :binary
  end

  def changeset(chunk) do
    chunk
    |> Map.put(:leaf, true)
    |> inspect_at("\n# updated map:")

    %__MODULE__{}
    |> cast(chunk, @required)
    |> inspect_at("\n# changeset")
  end

  defp inspect_at(chunk, label) do
    IO.puts label
    IO.inspect chunk
  end
end

When I attempt to run this in test, I’m seeing that the leaf field is getting dropped at the cast/3 step in the pipe. Subsequently the test fails because I have a not-null constraint on that field and it isn’t there.

Why is the boolean value getting dropped?

FWIW in my non-simplified real-app code, I have a second boolean in this schema. That field is also getting dropped.

Output from when I run the above during tests …

# updated map:
%{id: "86dc5ba945664a2eae561d82faec6d9b", leaf: true, payload: "testing 1, 2, 3"}

# changeset:
#Ecto.Changeset<action: nil,
 changes: %{id: "86dc5ba945664a2eae561d82faec6d9b", payload: "testing 1, 2, 3"},
 errors: [], data: #MyApp.Chunk<>, valid?: true>

Derp. Looked at the code one more time after posting. I was missing the assignment back to chunk.

2 Likes