This is a simple function used to insert or update some data. If user data is already in db i simply update it, otherwise i insert a new row with data. Everything works fine but i have a problem with validation. Changeset definition:
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name, :surname, :user_id])
|> validate_required([:name, :surname, :user_id])
|> unique_constraint(:user_id)
end
validate_required is currently working only during insert and not during update.
def add_or_change(user_id, new_data) do
data_from_db = data_by_user_id (user_id)
case data_from_db do
nil ->
Data.changeset(%Data{}, new_data)
|> Repo.insert()
_ ->
Changeset.change(data_from_db, new_data)
|> Repo.update()
end
end
If i try to insert "" as :name value, i get an error (can't be blank) as expected. However if i'm updating an existing row with "" as :name value, changeset does not pass through validation and my db is updated improperly. How to force validation also on change, before Repo.update()??
According to the doc: Ecto.Changeset/2
is meant for internal data changes, so it bypasses validations:
The function is meant for working with data internal to the application. Because of that neither validation nor casting is performed. This means
change/2
expects the keys in the changes map or keyword to be atoms.
You should use Ecto.Changeset.cast/4
to apply the validations, and then update if it is valid.