Hi everyone,
When you generate a context with phx.gen.context
, the generator creates a changeset function in the schema file that casts certain attributes and marks others as required. However, the id is neither cast nor required.
This changeset is then utilized in nearly all the generated functions within the context.
This works fine for most of the functions, but shouldn’t the changeset used in the update and delete functions of the context require the presence of the id in the struct?
I know that the code can be modified to do this, I thought that the generator should handle it. (if it’s good to do so)
Generally this is handled by fetching the structs from the database via Repo.get
etc; you don’t normally cast :id
in changesets.
Oh ok I see. I’m in a situation where if a query does not return anything, I am simply passed an empty struct so it’s a bit different
It looks You are checking the db before creating, or updating?
You might have race condition, and some other methods deals with this in a safer way.
I’m not really checking the database, I am just retrieving the struct to modify like @al2o3cr said. It’s just that my (simplified) workflow it’s like this: Repo.get(id) |> Map.put(something) |> changeset() |> Repo.update()
, but instead of failing on Repo.get!()
when there is no object I return an empty struct, and I fail on Repo.update()
because the struct has no PK.
Instead of changing the changeset
function I plan to call Repo.insert
if there is no PK instead of Repo.update
This will fail because Repo.get/3
returns nil when there’s no result and you can’t Map.put/3
on nil
This is called an “upsert” and ecto has support for it as described here.
1 Like
This will fail because Repo.get/3
returns nil when there’s no result and you can’t Map.put/3
on nil
I don’t exactly use Repo.get
, it was only a simplification.
This is called an “upsert” and ecto has support for it as described here.
Many thanks, I’ll look into it! 
If your pipeline can fail, You should use with…
with %{} = struct <- Repo.get(id),
data <- Map.put(struct),
changeset <- changeset(data),
any <- Repo.update(changeset) do
...
else
...
end