I am inserting a model A that contains a foreign key to another model B.
defmodule MyApp.ModelA do
use MyApp.Web, :model
schema "model_a" do
field :type, :string, null: false
field :data, :string, null: false
belongs_to :model_b, MyApp.ModelB
timestamps()
end
@required_fields ~w(type data)
@optional_fields ~w()
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @required_fields, @optional_fields)
|> assoc_constraint(:model_b)
end
end
and the Model B:
defmodule MyApp.ModelB do
use MyApp.Web, :model
schema "model_b" do
field :username, :string
field :pass, :string
has_many :model_a, MyApp.ModelA
timestamps()
end
@required_fields ~w(username pass)
@optional_fields ~w()
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, @required_fields, @optional_fields)
|> cast_assoc(:model_a)
|> validate_required([])
end
end
Model B exists, as I can get it via Repo.all(ModelB).
Model A changeset is successfully validated, and I can see the model_b_id value when I print model A changeset struct.
But when inserted, the reference is not inserted. Although I can see it when printing the changeset of model A, in the MySQL log, this field is completely missing, is not in the INSERT query.
I have played a little bit, and if I force this reference field to not be null in the MySQL table, then I get a {"does not exist", []}
for this foreign key field when inserting as a Repo.insert(...) response, although the model B exists in database.
model_b_id
in the changeset? Your@optional_fields
is empty according to the code you just posted. Can you try addingmodel_b_id
to@optional_fields
? – Raimentchangeset
andRepo.insert
fromiex
and post the whole output with the exact query that was sent from Ecto to the MySQL server? I can't think of any reason for Ecto to not send a field to the server. – Raiment