Phoenix Ecto:未插入外键

Dav*_*vid 5 elixir ecto phoenix-framework

我正在插入一个包含外键的模型A到另一个模型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
Run Code Online (Sandbox Code Playgroud)

和模型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
Run Code Online (Sandbox Code Playgroud)

模型B存在,因为我可以通过Repo.all(ModelB)获得它.

模型变更集已成功验证,我可以在打印模型A变更集结构时看到model_b_id值.

但插入时,未插入引用.虽然我在打印模型A的变更集时可以看到它,但在MySQL日志中,此字段完全缺失,不在INSERT查询中.

我玩了一点,如果我强制这个引用字段在MySQL表中不为null,那么{"does not exist", []}当插入一个Repo.insert(...)响应时,我得到一个这个外键字段,尽管模型B存在于数据库中.

小智 0

我不认为 Ecto 会为你从结构中取出 ID 字段 - 我一直在做这样的事情:

\n\n
defmodule MyApp.ModelA do\n  use MyApp.Web, :model\n\n  schema "model_a" do\n    field :type, :string, null: false\n    field :data, :string, null: false\n    belongs_to :model_b, MyApp.ModelB\n    timestamps()\n  end\n\n  @required_fields ~w(type data model_b_id)\n  @optional_fields ~w()\n\n  @doc """\n  Method head to define what\'s coming.\n  """\n\xc2\xa0\xc2\xa0def changeset(model, params \\\\ :empty)\n\n  @doc """\n  Catches the case where you\'re passing in a model_b struct instead of an integer.\n  Just makes a recursive call with the correct type.\n  """\n\xc2\xa0\xc2\xa0def changeset(model, %{model_b_id: nil, agency: %MyApp.ModelB{} = model_b} = params) do\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0changeset(model, %{params | model_b_id: model_b.id})\n\xc2\xa0\xc2\xa0end\n\n  @doc """\n  I normally use assoc_constraint on the table index itself like so\n  """\n  def changeset(struct, params \\\\ %{}) do\n    struct\n    |> cast(params, @required_fields, @optional_fields)\n    |> assoc_constraint(:model_b, name: :model_as_model_b_id_fkey)\n  end\nend\n
Run Code Online (Sandbox Code Playgroud)\n