【发布时间】:2016-12-17 01:59:19
【问题描述】:
我正在插入一个模型 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
和模型 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
模型 B 存在,因为我可以通过 Repo.all(ModelB) 获得它。
模型 A 变更集已成功验证,当我打印模型 A 变更集结构时,我可以看到 model_b_id 值。
但是插入时,引用没有插入。虽然我可以在打印模型 A 的变更集时看到它,但在 MySQL 日志中,该字段完全缺失,不在 INSERT 查询中。
我玩了一点,如果我强制这个引用字段在 MySQL 表中不为空,那么当作为 Repo.insert(...)响应,尽管模型 B 存在于数据库中。
【问题讨论】:
-
变更集验证不检查外键验证,因此在实际尝试插入之前不会出现“不存在”错误。您能否发布模型的架构、您运行的代码和 SQL 日志?
-
对不起,也许我没有解释自己。我得到“不存在”作为 Repo.insert(...) 的响应。对于这种情况,变更集验证确实总是可以正常工作。
-
您确定您在变更集中看到
model_b_id吗?根据您刚刚发布的代码,您的@optional_fields为空。您可以尝试将model_b_id添加到@optional_fields吗? -
是的,如果我在创建和验证变更集后打印变更集,我绝对可以看到它。我在变更集的 model_b_id 字段中看到了 ModelB 行的 id。注意模型A中的这个引用字段是在迁移中添加的,所以在原始表定义中没有定义,但我认为它没有什么关系。我创建了一个额外的新字段,并且能够为其设置一个值。因此,在迁移中定义它应该没有任何关系。
-
我已经尝试在 required_fields 中添加这个 model_b_id 字段(以及第二次尝试在 optional_fields 中),我一直遇到同样的问题,但是变更集验证没有抱怨,所以这意味着字段值实际上是放。问题是当 Repo.insert(..).
标签: elixir phoenix-framework ecto