如何将关联传递给 Ecto 中的变更集?

How can I pass association to changeset in Ecto?

我有一个非常简单的 Comment 模型:

  schema "comments" do
    field :content, :string
    belongs_to :user, MyApp.User
    timestamps
  end

我想创建一个新记录,我想要 changeset 验证该用户是否存在。我该怎么做?

我的 ecto 版本是 1.1.8

正确的做法是让数据库处理数据的完整性。在您的应用程序中为此编写检查很容易出现竞争条件。如果在验证和插入 Comment 之间删除 User 怎么办?如果 User 和任何现有的 Comment 被删除怎么办?在数据库中处理这个将确保您的数据库中永远不会有无效数据。

首先,确保 user_id 字段设置为 references(:users):

create table(:comments) do
  ...
  # Check out the various :on_delete options you can pass to here: https://hexdocs.pm/ecto/Ecto.Migration.html#references/2
  add :user_id, references(:users, on_delete: :nilify_all)
end

然后,在您的 changeset 函数中,在管道传输到 cast 之后,添加:

|> Ecto.Changeset.assoc_constraint(:user)

这会将数据库返回的与 user_id 相关的错误转换为正常的变更集错误。您可以阅读更多关于 Ecto.Changeset.assoc_constraint/3 here. Also see Ecto.Changeset.html#foreign_key_constraint/3.