假设我有Post
belongs_to
的模型Category
:
defmodule MyApp.Post do
use MyApp.Web, :model
schema "posts" do
field :title, :string
belongs_to :category, MyApp.Category
end
def changeset(model, params) do
model
|> cast(params, [:title, :category_id)
|> validate_required([:title, :category_id])
|> assoc_constraint(:category)
end
end
问题是:如果我没有将category_id
传递给params,则更改集错误键为:category_id
,但在assoc_constraint
失效时(如果类别不存在),我有category
键。这对我来说有点懊悔 - 因为问题实际上是相同的 - 没有帖子类别。我该如何处理?
答案 0 :(得分:0)
在阅读Ecto的源代码后,我能找到的唯一方法就是将错误中的名称作为字段提供给assoc_constraint
,然后自己覆盖约束名称。 belongs_to约束的默认名称是#{table name}_#{column in table}_fkey
(source)。
修改:如果我们自己传递foreign_key_constraint
,我们也可以使用:name
,因为assoc_constraint
唯一没有foreign_key_constraint
做的事情。我已经更新了以下代码。
迁移:
defmodule MyApp.Repo.Migrations.CreateComment do
use Ecto.Migration
def change do
create table(:comments) do
add :post_id, references(:posts, on_delete: :nothing)
timestamps()
end
create index(:comments, [:post_id])
end
end
型号:
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:post_id])
|> validate_required([:post_id])
|> foreign_key_constraint(:post_id, name: :comments_post_id_fkey)
end
演示:
iex(1)> Comment.changeset(%Comment{}, %{}).errors
[post_id: {"can't be blank", []}]
iex(2)> Comment.changeset(%Comment{}, %{post_id: 999}).errors
[]
iex(3)> {:error, changeset} = Comment.changeset(%Comment{}, %{post_id: 999}) |> Repo.insert; changeset.errors
[post_id: {"does not exist", []}]
iex(4)> Comment.changeset(%Comment{}, %{post_id: 1}) |> Repo.insert
{:ok,
%MyApp.Comment{__meta__: #Ecto.Schema.Metadata<:loaded, "comments">,
id: 1, inserted_at: #Ecto.DateTime<2016-07-29 06:25:24>,
post: #Ecto.Association.NotLoaded<association :post is not loaded>,
post_id: 1, updated_at: #Ecto.DateTime<2016-07-29 06:25:24>}}