Consider a schema with the following settings for the primary key:
@primary_key {:id, :binary_id, autogenerate: false}
In this case, we’re using server generated UUIDs in some cases. For a regular insert, this is fine. I just pass in returning: [:id]
. However, this is problematic for cast_assoc/3
. The related models get created in the database but Ecto doesn’t set the keys on the parent model.
Here is a contrived example:
defmodule NS.User do
use Ecto.Schema
@primary_key {:id, :binary_id, autogenerate: false}
@foreign_key_type :binary_id
schema "users" do
belongs_to :profile, NS.Profile, on_replace: :update
end
end
defmodule NS.Profile do
use Ecto.Schema
@primary_key {:id, :binary_id, autogenerate: false}
@foreign_key_type :binary_id
schema "user_profiles" do
field :name, :string
end
end
attrs = %{profile: %{name: "Name"}}
user
|> cast_assoc(:profile, attrs)
|> NS.Repo.insert(returning: [:id])
The NS.Profile
does get created, but it’s not associated with NS.User
(:profile_id
is nil
, even after a reload). Setting autogenerate
to true
fixes this issue. However, I imagine for integer keys the value coming back from the server is being used and is not generated by the application.
For now, autogenerating UUIDs for some models is fine, but there are other models where this is being done server-side and we want that functionality. What can I do to make those situations work with cast_assoc/3
?
Using Ecto 3.8.4.