How to get current(or old?) value of field from an Ecto changeset?

I am currently using the following snippet to do it

    old_value =
      cs
      |> Map.get(:data, %{})
      |> Map.get(field, %{})

Is it the right way? I didn’t find a suitable function in Ecto docs, get_field gives the current change if it exists, but I want to get current(or old, not sure about the term) value, if there is a change or not.

Ecto version is 2.1.6.

Yes, it is. But since you expect both the data field and the field itself to exist, you should do: changeset.data.name_of_the_field, as it will raise if you have a typo.

3 Likes

I think I’m fine not raising here, since I am not expecting the field to exist in all cases, hence the default value of %{} in calls.
I think data field always exists, so no gain in choosing between . and get. And I expect the field to be non-existent in some cases, or to be even nil sometimes. Raising wouldn’t be an option for me.
Thanks!

You should use the . notation for :data. When using get for data, I read your code as: get the :data field but if it doesn’t exist, get nil. You imply that :data might not exist, however it always does, so it is misleading. There’s many ways to access a field but you gotta use the way that makes more sense for readability.

I’m sure you’re right. Totally.
But actually changing a code that is running for like 2 years just to make this change is frustrating. I’m sure you know what it means :slight_smile:
Thanks buddy.

BTW, Referring to data in changeset without using Optimistic Locking is unreliable (except it is schema less or very special use case).