How to check if struct is persisted or not?
Asked Answered
C

2

8

Is there a way to figure out if struct is persisted or not? I started digging source for Ecto's insert_or_update but with no luck as it hits some private method. I want to accoplish something like this:

def changeset(struct, params \\ %{}) do
  struct
  |> cast(params, [:whatever]
  |> do_a_thing_on_unsaved_struct 
end

defp do_a_thing_on_unsaved_struct(struct) do
  case ARE_YOU_PERSISTED?(struct) do
    :yes -> struct
    :no  -> do_things(struct)
  end
end

Is it possible, or I'm doing something dumb?

Claque answered 25/3, 2017 at 4:53 Comment(0)
M
13

You can check the .__meta__.state of the struct. If it's a new one (not persisted), it'll be :built, and if it was loaded from the database (persisted), it'll be :loaded:

iex(1)> Ecto.get_meta(%Post{}, :state)
:built
iex(2)> Ecto.get_meta(Repo.get!(Post, 1), :state)
:loaded
Modestamodeste answered 25/3, 2017 at 4:57 Comment(4)
That's it. Thanks. I also found Ecto.get_meta(struct, :state). My tests are getting tripped up on something, but it's probably my factories.Claque
Actually, it seems that somehow I get Ecto.Changeset fed instead of struct I'd expect: key :__meta__ not found in: #Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #PedalApp.Waypoint<>, valid?: true> Even though it's coming from Repo.get!. What's going on here?Claque
Nevermind, I'm actually passing changeset, not original struct there.Claque
You can get the struct from the changeset using .data, so that'll be Ecto.get_meta(changeset.data, :state).Modestamodeste
S
1

You can check struct.data.id if the struct's primary key is id:

defp do_a_thing_on_unsaved_struct(struct) do
  if struct.data.id, do: struct, else: do_things(struct)
end
Sardonic answered 18/6, 2020 at 5:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.