Custom validation does not work

I am trying to do some custom validations but there was a problem and to debug it I made it very simple:

  def validate_birthdate(changeset, field) do
    Logger.debug("++++")

    validate_change(changeset, field, fn _, _  ->
      Logger.debug("****")
      []
    end)
  end

But even In this simple form “****” won’t be printed. What I have done wrong?

The passed in field probably didn’t change at all.

The field birthdate is new and its value is NULL for all rows in the database also I am trying to create a new record not updating an existing one. I can see the new value passed to the server from the browser "user" => %{"birthdate" => "2000-1-1", ...........} and the function is called in the changeset like this:

  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :username, :birthdate])
    |> validate_required([:name, :username])
    |> validate_length(:username, min: 1, max: 255)
    |> validate_birthdate(:birthdate)
    |> unique_constraint(:username)
  end

So I think it has changed.

Can you please show the schema? Perhaps the field couldn’t be cast, then a further validation does not happen iirc.

Here is the schema (based on the phoenix book) and in this case it should be using registration_changeset:

defmodule Myapp.Accounts.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias Myapp.Accounts.Credential
  require Logger

  schema "user" do
    field :name, :string
    field :username, :string
    field :birthdate, :date
    has_one :credential, Credential

    timestamps()
  end

  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :username, :birthdate])
    |> validate_required([:name, :username])
    |> validate_length(:username, min: 1, max: 255)
    |> validate_birthdate(:birthdate)
    |> unique_constraint(:username)
  end

  def registration_changeset(user, params) do
    user
    |> changeset(params)
    |> cast_assoc(:credential, with: &Credential.changeset/2, required: true)
  end

  def validate_birthdate(changeset, field) do
    Logger.debug("++++")

    validate_change(changeset, :birthdate, fn _, _  ->
      Logger.debug("****")
      []
    end)
  end
end

"2000-1-1" is not a proper date. Please use an example which uses a proper parsable date. 4 digit year and 2 digits each for month and day.

3 Likes

Thanks, using that format solved it.