Ecto converting empty string into nil

I have non null columns with default value set to "". When I try to update it, Ecto cast is converting column value of "" into nil and update operation fails with ERROR 23502 (not_null_violation) null value in column "column" violates not-null constraint. I have default value set in schema too not that it should matter at all.
I dont understand why Ecto is converting empty string to nil. Sounds wired.

1 Like

Because some sources can send empty string in case of empty text field. You can change this behaviour in changes by using empty_values: [] in the cast/4.

4 Likes

Thanks it worked.

I hope it was other way around. Implicit change is confusing, I would prefer explicitly setting which fields to make nil.

As Ecto was designed to work with input from web, it is natural choice to assume that empty string is nullable. Because as I said, there is no way to deduce if the non-filled text form is null or empty string.

However that happens only in cast/4 which (as the name suggest) will try to cast the input to the respective types. In such casting I would assume that empty fields should be counted as NULLs. In all other situations it will correctly use NULL only when specified as such.

1 Like

I would disagree, for me empty string and null are very different, empty string can mean user has chosen to leave field empty and null can mean that user has not touched that field at all.

1 Like

And how would you detect what was the user intention? How would browser deduce that so it could set the request parameters accordingly? There is too much UX horror there to make such decisions. The current approach of cast/4 is what 90% of users are expecting from it, and in case of other needs - you can always set your options accordingly to your needs.

Not to say that for some DBs (like MySQL InnoDB) the empty string and NULL are equivalent.

1 Like

Null and empty string are indeed very different, but that‘s only useful if the data format coming into the system can represent both distinctly. E.g. json can do so. The available encodings for html based forms can’t. All you got is strings here; and in the vast majority of cases empty strings in their data represents null.

3 Likes

Since this is convention in Ecto I would urge not to override default behaviour.

Just my 2c here - I’m working with JSON, and so I had the exact same question as @quazar .

Explaining that html-based forms can’t distinguish between null and an empty string, really helped me understand this design decision. Elixir-generated templates, and with that, html forms, being an important part of many elixir / phoenix apps, I can totally live with that. But before this knowledge I was truly in the blind.

Thanks!