在没有预加载的情况下检索 Ecto 关系的 ID
Retrieve ID of Ecto relationship without preload
假设我有两个 Ecto 模型(以及它们的迁移):
schema "projects" do
field :name, :string
belongs_to :client, MyApp.Client
timestamps
end
create table(:projects) do
add :name, :string
add :client_id, references(:clients)
timestamps
end
schema "clients" do
field :name, :string
has_many :projects, MyApp.Project
timestamps
end
create table(:clients) do
add :name, :string
timestamps
end
如果我查询过项目模型,例如
project = Repo.get!(Project, proj.id)
不出所料,我无法访问 project.client.id
,因为我没有在查询中使用 preload
。
每当我尝试访问 project.client_id
它 returns 无。当然我应该能够访问外键 ID 本身?
希望下面的代码能更好地说明:
client = Repo.insert!(%Client{name: "Test Client"})
proj = Repo.insert!(%Project{name: "Test Project 1", client: client})
project = Repo.get!(Project, proj.id)
assert project.client_id != nil
# ^ This always fails because project.client_id is nil
这里的问题是您构建 proj
的方式导致 client_id
字段从未被填充。您可以通过检查您的数据库来验证这一点。
您可以使用Ecto.Model.build/3从客户端创建项目:
proj = build(client, :projects, %{name: "Test Project 1"}) |> Repo.insert!
尝试直接设置字段(正如有人已经提到的):
proj = Repo.insert!(%Project{name: "Test Project 1", client_id: client.id})
另一种方法是直接在项目上设置客户端的 ID。
client = Repo.insert!(%Client{name: "Test Client"})
proj = Repo.insert!(%Project{name: "Test Project 1", client_id: client.id})
存储在 :client 中的关联会在您更新 :client_id 时自动更新,因为 Ecto 知道两者是相关的。
假设我有两个 Ecto 模型(以及它们的迁移):
schema "projects" do
field :name, :string
belongs_to :client, MyApp.Client
timestamps
end
create table(:projects) do
add :name, :string
add :client_id, references(:clients)
timestamps
end
schema "clients" do
field :name, :string
has_many :projects, MyApp.Project
timestamps
end
create table(:clients) do
add :name, :string
timestamps
end
如果我查询过项目模型,例如
project = Repo.get!(Project, proj.id)
不出所料,我无法访问 project.client.id
,因为我没有在查询中使用 preload
。
每当我尝试访问 project.client_id
它 returns 无。当然我应该能够访问外键 ID 本身?
希望下面的代码能更好地说明:
client = Repo.insert!(%Client{name: "Test Client"})
proj = Repo.insert!(%Project{name: "Test Project 1", client: client})
project = Repo.get!(Project, proj.id)
assert project.client_id != nil
# ^ This always fails because project.client_id is nil
这里的问题是您构建 proj
的方式导致 client_id
字段从未被填充。您可以通过检查您的数据库来验证这一点。
您可以使用Ecto.Model.build/3从客户端创建项目:
proj = build(client, :projects, %{name: "Test Project 1"}) |> Repo.insert!
尝试直接设置字段(正如有人已经提到的):
proj = Repo.insert!(%Project{name: "Test Project 1", client_id: client.id})
另一种方法是直接在项目上设置客户端的 ID。
client = Repo.insert!(%Client{name: "Test Client"})
proj = Repo.insert!(%Project{name: "Test Project 1", client_id: client.id})
存储在 :client 中的关联会在您更新 :client_id 时自动更新,因为 Ecto 知道两者是相关的。