【发布时间】:2021-07-19 03:02:45
【问题描述】:
我正在尝试在 Ecto 内部的 Rails 中复制我习惯的行为。在 Rails 中,如果我有 Parent 和 Child 模型,并且 Child 属于 Parent,我可以这样做:Child.create(parent: parent)。这会将Child 的parent_id 属性分配给parent 的ID。
这是我的最小 Ecto 示例:
defmodule Example.Parent do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "parent" do
has_many :children, Example.Child
end
def changeset(parent, attributes) do
parent |> cast(attributes, [])
end
end
defmodule Example.Child do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "child" do
belongs_to :parent, Example.Parent
end
def changeset(child, attributes) do
child
|> cast(attributes, [:parent_id])
end
end
这是我想要的行为示例:
parent = %Example.Parent{id: Ecto.UUID.generate()}
changeset = Example.Child.changeset(%Example.Child{}, %{parent: parent})
# This should be the parent's ID!
changeset.changes.parent_id
我尝试了什么
我已经尝试了几种不同的方法来让它在 Ecto 中工作,但我一直在做空。
child
|> cast(attributes, [:parent_id])
|> put_assoc(:parent, attributes.parent)
这似乎没有分配关联。
我尝试直接投射关联:
child
|> cast(attributes, [:parent_id, :parent])
但这会产生一个RuntimeError,告诉我使用cast_assoc/3。这似乎不是我想要的,但我还是尝试了。
child
|> cast(attributes, [:parent_id])
|> cast_assoc(:parent, with: &Example.Parent.changeset/2)
这会产生一个Ecto.CastError。
最后,我尝试从cast_assoc/3 中删除:with 选项。
child
|> cast(attributes, [:parent_id])
|> cast_assoc(:parent)
但我遇到了同样的错误。
【问题讨论】:
-
您的情况应该是,仅在变更集中使用
cast_assoc或强制转换parent_id。不要同时使用。 -
如果你已经有了 ids...为什么不把 ids 和它关联起来呢?无论如何,这就是所有正在发生的事情。喜欢
changeset = Example.Child.changeset(%Example.Child{}, %{parent_id: parent.id})。还有为什么不直接使用 Context 方法,比如Example.Child.create_child(%{parent_id: parent_id}) -
我想我觉得我不应该担心它。当模式中存在关联时,Repo 方法会自动处理它,所以我觉得变更集也应该如此。而且我没有使用 create_child,因为我的一些模式是两个现有记录之间的连接。
标签: elixir phoenix-framework ecto