如何检查结构是否持久化?

How to check if struct is persisted or not?

有没有办法判断结构是否持久化?我开始挖掘 Ecto 的 insert_or_update 的源代码,但运气不佳,因为它遇到了一些私有方法。我想完成这样的事情:

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

有可能吗,还是我在做蠢事?

您可以检查结构的.__meta__.state。如果它是新的(未持久化),它将是 :built,如果它是从数据库加载的(持久化),它将是 :loaded:

iex(1)> Ecto.get_meta(%Post{}, :state)
:built
iex(2)> Ecto.get_meta(Repo.get!(Post, 1), :state)
:loaded

您可以检查 struct.data.id 结构的主键是否为 id:

defp do_a_thing_on_unsaved_struct(struct) do
  if struct.data.id, do: struct, else: do_things(struct)
end