validationelixirphoenix-frameworkectochangeset

Ecto Changeset functions not getting called on update


When inserting using a changeset in Ecto, it calls my debug function, and properly checks that everything is in order according to the changeset:

iex> User.changeset(%User{}, %{username: "username"})
#Ecto.Changeset<
  action: nil,
  changes: %{},
  errors: [
    email: {"can't be blank", [validation: :required]}
  ],
  data: #Api.User<>,
  valid?: false
>

However, when using update, my changeset functions never get called. I assume this is on purpose, as it wouldn't need to check if a field is required if only updating one field, however I have other functions in there such as auto_hash which uses a virtual password field to hash the password on update, and this cannot be called on update if the changeset functions never get called.

So my question is: is there a way to set up a similar thing to a changeset function that only gets called on update?

By 'on update', I mean when doing the following:

iex> user = Repo.get_by(User, email: "email")
iex> changeset = Ecto.Changeset.change(user, [ password: "password", password_confirmation: "password" ])
iex> Repo.update(changeset)

Solution

  • It looks like you aren't calling your changeset function. Ecto.Changeset.change/2 doesn't magically know where your specific function is: you have to call your own changeset function e.g. User.changeset(existing_user_data, new_data) -- this assumes that you've named your function changeset and you've defined it inside your User module. You might maintain multiple changeset functions, e.g. one for inserting new data and another for updating data.