After inserting data to my database, I find it difficult to update the record because of required validation on two virtual fields (:password and :password_confirmation) which I do not need during updates. I only require this fields when creating the user.
I tried removing the validation on those fields, but with this I cannot validate data at creation of the user.
User schema
defmodule TodoBackend.User.Model.User do
use Ecto.Schema
import Ecto.Changeset
import Argon2, only: [hash_pwd_salt: 1]
schema "users" do
field :email, :string
field :name, :string
field :phone, :string
field :password_hash, :string
# Virtual fields:
field :password, :string, virtual: true
field :password_confirmation, :string, virtual: true
timestamps()
end
@doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:email, :name, :phone, :password, :password_confirmation])
|> validate_required([:email, :name, :phone, :password, :password_confirmation])
|> validate_format(:email, ~r/@/) # Check that email is valid
|> validate_length(:password, min: 8) # Check that password length is >= 8
|> validate_confirmation(:password) # Check that password === password_confirmation
|> unique_constraint(:email)
|> put_password_hash
end
defp put_password_hash(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{password: pass}}
->
put_change(changeset, :password_hash, Argon2.hash_pwd_salt(pass))
_ ->
changeset
end
end
end
User controller function to update user
def update(conn, %{"id" => id, "user" => user_params}) do
user = UserRepo.get_user!(id)
IO.inspect(user)
with {:ok, %User{} = user} <- UserRepo.update_user(user, user_params) do
render(conn, "show.json", user: user)
end
end
Ecto repo def
def update_user(%User{} = user, attrs) do
user
|> User.changeset(attrs)
|> Repo.update()
end
Actual result: I get this error {"errors":{"password":["can't be blank"],"password_confirmation":["can't be blank"]}}
Expected result: I want the validation to still be in place and only specified field should be updated