Elixir-Exto:如何验证外键约束?

Elixir-Exto:如何验证外键约束?,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,我正在使用Elixir和Phoenix web框架,但现在我一直在尝试验证外键约束。因此,给定一个带有许多注释的模型Post,我编写了Comment模型,如下所示: defmodule MyApp.Comment do use MyAPp.Web, :model schema "comments" do field :body, :text belongs_to :post, MyApp.Post timestamps end @required_f

我正在使用Elixir和Phoenix web框架,但现在我一直在尝试验证外键约束。因此,给定一个带有许多注释的模型
Post
,我编写了
Comment
模型,如下所示:

defmodule MyApp.Comment do
  use MyAPp.Web, :model

  schema "comments" do
    field :body, :text
    belongs_to :post, MyApp.Post

    timestamps
  end

  @required_fields ~w(body post_id)
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
    |> foreign_key_constraint(:post_id)
  end
end
及其单元测试:

defmodule MyApp.CommentTest do
  # [...]
  test "changeset with non existent post" do
    attrs = %{
      body: "A comment."
      post_id: -1 # some non-existent id?
    }
    refute Comment.changeset(%Comment{}, attrs).valid?
    assert {:post_id, "does not exist"} in errors_on(%Comment{}, %{})
  end
end
根据:

外键约束依靠数据库进行检查 如果关联的模型存在或不存在。这有助于保证 仅当数据库中存在父项时,才会创建子项 也是

我希望我编写的代码能够工作,相反,它只检查是否存在(如
@required\u fields~w(body post\u id)
中所定义的)。我不排除我做错了什么或误解了文件中的陈述

有没有人已经发现了这一点

更新: 为完整起见,以下是迁移:

def change do
  create table(:comments) do
    add :body, :text
    add :post_id, references(:posts)

    timestamps
  end

  create index(:comments, [:post_id])
end
“依赖数据库”意味着您需要在数据库模型中具有外键约束

在您的迁移过程中,您应该有如下内容:

create table(:comments) do
  add :post_id, references(:posts)
end

它在父表和子表之间强制执行外键约束检查。

因为它依赖于数据库,所以需要在迁移中添加引用并执行实际的数据库操作。您必须调用
Repo.insert/1
Repo.update/1
给出更改集,然后它将返回
{:error,changeset}

记住,在长生不老药和外胚层中都没有物体。因此,
changeset.valid?
永远无法执行数据库操作,它只是反映要执行的一组更改的数据,并且在执行插入或更新等操作时,此数据的状态会发生转换

最后一点注意,
errors\u on/2
总是会返回一个新的变更集,而不是您目前正在使用的变更集。您的最后一行可能是:

assert {:post_id, "does not exist"} in changeset.errors

你也可以提供你的迁移吗?@Gazler编辑了我的问题,添加了迁移。事实上,我已经在迁移中这样做了。我已经更新了我的问题并添加了迁移代码。非常感谢您的完整回答。在本例中,问题出在别处:在对迁移进行了一些修改之后,我没有重新创建测试数据库。因此,模式没有约束。而且,我做了你建议的改变。再次感谢你!:-)