I have a User model
schema "users" do
field :email, :string
field :username, :string
field :password, :string, virtual: true
# .. some more fields
has_one :user_profiles, UserProfile, on_delete: :delete_all
timestamps()
end
def registration_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:email, :password, :username])
|> validate_required([:email, :password, :username])
# .. some more functions
|> put_assoc(:user_profiles, UserProfile.changeset(%UserProfile{}, params), required: true)
end
and a UserProfile model
schema "user_profiles" do
field :first_name, :string, default: ""
field :last_name, :string, default: ""
# ... some more fields
belongs_to :users, User
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:first_name, :last_name,
# ... rest of the fields
])
# ... some validators etc
end
In the registration_changeset/2 function, the params parametter, is a map that has all the fields. So at the end I do get a valid changeset that has the UserProfile changeset as an association. So far the User and UserProfile are not created yet in the database.
When I try
Repo.insert changeset
I get an exception
** (Postgrex.Error) ERROR (not_null_violation): null value in column “user_id” violates not-null constraint
table: user_profiles column: user_id
So it seems that Ecto first inserts the User in the database then proceeds to insert the UserProfile. But it does not pass the id of the newly created model to the belongs_to :users, User
field.
How can it be that it creates both the user and the profile in one insert?