al2o3cr

al2o3cr

`Ecto.Changeset.validate_change` and setting fields to `nil`

Question / comment / maybe bug report

I was surprised that this didn’t work:

def validate_not_cleared(changeset) do
  validate_change(changeset, :some_field, fn _, _new_value ->
    if changeset.data.some_field do
      [some_field: "can't be changed once set"]
    else
      []
    end
  end)
end

It successfully adds an error to the changeset when some_field is being changed to a non-nil value, but if the changeset is clearing the value it doesn’t run:

%SomeStruct{some_field: "foo"}
|> Ecto.Changeset.change(%{foo: nil})
|> validate_not_cleared()
# gives valid?: true

Here’s what I’m using instead, for the moment:

def validate_not_cleared(changeset) do
  case fetch_change(changeset, :some_field) do
    {:ok, _new_value} ->
      if changeset.data.some_field do
        add_error(changeset, :some_field, "can't be changed once set")
      else
        changeset
      end

    :error ->
      changeset
  end
end

EDIT: this is also distinct from how Ecto.Changeset.update_change works, which uses fetch_change

Most Liked

josevalim

josevalim

Creator of Elixir

As the docs say (emphasis mine):

It invokes the validator function to perform the validation only if a change for the given field exists and the change value is not nil.

https://hexdocs.pm/ecto/Ecto.Changeset.html#validate_change/3

That’s because most validations do not want to run on nil. You have one of the few exceptions. :slight_smile:

al2o3cr

al2o3cr

Oops, that was a typo between the real code and the sanitized-for-public consumption version! Good catch!

Where Next?

Popular in Questions Top

JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New

Other popular topics Top

dotdotdotPaul
Okay, I'm having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I'm sure I'...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New

We're in Beta

About us Mission Statement