我正在使用Ecto(2.2.8)来处理现有的PostgreSQL
数据库。
我定义了两个模式来表示owner
和house
。 house
架构有一个FK(belongs_to
)owner
。我为house
定义了一个模式和变更集,如下所示:
@primary_key {:id, :id, autogenerate: true}
schema "house" do
belongs_to :owner, Owner, foreign_key: :owner_id
field :name, :string
end
def changeset(house, params \\ %{}) do
house
|> cast(params, [:name, :owner_id])
|> validate_required([:owner_id])
|> foreign_key_constraint(:owner_id)
end
问题
如果数据库中没有{:error, changeset}
owner
的{{1}}记录,我希望以下代码返回元组id
:
10
但是,我收到了 Postgrex.Error :
House.changeset(%House{}, %{name: "Whatever", owner_id: 10}) |> Repo.insert
。
如果我在致电** (Postgrex.Error) ERROR 23503 (foreign_key_violation): insert or update on table "house" violates foreign key constraint "house_owner_id_fkey"
之前检查changeset.constraints
的内容,这就是我得到的:
Repo.insert
所以,当使用House.changeset(%House{}, %{name: "Whatever", owner_id: 10})
|> Map.get(:constraints)
[
%{
constraint: "house_owner_id_fkey",
error: {"does not exist", []},
field: :owner_id,
match: :exact,
type: :foreign_key
}
]
时,我不应该得到一个元组foreign_key_constraint
,我可以按照文档的建议进行模式匹配吗?
更新:
我没有使用Ecto的迁移。已创建数据库表,并且迁移由不同的项目处理。 SQL Schema看起来像这样:
{:error, changeset}
答案 0 :(得分:0)
这很奇怪。我有一个非常类似的方案,它按预期工作,具有相同的约束。
defmodule Hello.Accounts.Credential do
use Ecto.Schema
import Ecto.Changeset
alias Hello.Accounts.{Credential, User}
schema "credentials" do
field :email, :string
belongs_to :user, User, foreign_key: user_id
timestamps()
end
@doc false
def changeset(%Credential{} = credential, attrs) do
credential
|> cast(attrs, [:email, :user_id])
|> validate_required([:email, :user_id])
|> unique_constraint(:email)
|> foreign_key_constraint(:user_id)
end
end
当我插入无效记录(不存在的user_id)时:
Credential.changeset(%Credential{}, %{email: "test@c.c", user_id: 2}) |> Repo.insert
{:error,
#Ecto.Changeset<action: :insert, changes: %{email: "test@c.c", user_id: 2},
errors: [user_id: {"does not exist", []}], data: #Hello.Accounts.Credential<>,
valid?: false>}
但是,之前出现了同样的错误,但我认为在使用此任务重置数据库时它已修复:
mix ecto.drop
mix ecto.create
mix ecto.migrate
mix run priv/repo/seeds.exs
该任务重新创建数据库并运行迁移。
凭据SQL架构:
Table "public.credentials"
Column | Type | Modifiers
-------------+-----------------------------+----------------------------------------------------------
id | bigint | not null default nextval('credentials_id_seq'::regclass)
email | character varying(255) |
user_id | bigint | not null
inserted_at | timestamp without time zone | not null
updated_at | timestamp without time zone | not null
Indexes:
"credentials_pkey" PRIMARY KEY, btree (id)
"credentials_email_index" UNIQUE, btree (email)
"credentials_user_id_index" btree (user_id)
Foreign-key constraints:
"credentials_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
Project DB Dependencies:
Phoenix-Ecto - &gt; 3.2 Postgresx&gt; = 0.0.0