我想要一个虚拟的关联,这样我就可以做多态关联。所以我有一个图片架构,与用户(和其他人)有关。我将在回调中有一个位置,我将多态类型/ id分配给模式,但为了做到这一点,需要将其分配给更改,但是这样我才挣扎。目前我有。
defmodule App.Picture do
schema "pictures" do
...
field :pictureable, :map, virtual: true
end
@attrs [:picture, :pictureable_id, :pictureable_type]
def changeset(picture, attrs) do
picture
|> cast(attrs, @attrs ++ [:pictureable])
|> handle_polymorphic
|> cast_attachments(attrs, [:picture])
|> validate_required(@attrs)
end
def handle_polymorphic(%{changes: %{pictureable: %type{id: id}}} = ch) do
ch
|> put_change(:pictureable_type, type)
|> put_change(:pictureable_id, id)
end
end
相当直截了当。您可以使用像%{picture: Path.to("/image"), pictureable: user}
这样的attrs创建图片,这些图片会转换为%{picture: Arc.stuff, pictureable_id: 1, pictureable_type: "App.User"}
上述代码的问题是:pictureable
没有保留在变更集中
pic = %Plug.Upload{content_type: ...}
user = insert(:user)
args = %{picture: img, pictureable: user}
ch = Picture.changeset(%Picture{}, args)
我的变更集就像这样回来了
#Ecto.Changeset<
action: nil,
changes: %{
picture: %{
file_name: "10x10.png",
updated_at: #Ecto.DateTime<2018-05-05 18:59:18>
}
},
errors: [
pictureable_id: {"can't be blank", [validation: :required]},
pictureable_type: {"can't be blank", [validation: :required]},
pictureable: {"is invalid", [type: :map, validation: :cast]}
],
data: #App.Picture<>,
valid?: false
>
为什么不按预期为虚拟架构分配地图?
编辑:如果我使用field :pictureable, :any, virtual: true
,它会起作用。因此,即使用户通过is_map(user)
测试,结构也不是地图似乎存在一些问题。不知道为什么它被视为不是地图?
答案 0 :(得分:0)
我最初的倾向是完全没有投射出可画面,因为你真的不想让Ecto捣乱数据类型...
def changeset(picture, attrs) do
picture
|> cast(attrs, @attrs ++ [:pictureable])
|> handle_polymorphic(attrs[:picturable])
|> cast_attachments(attrs, [:picture])
|> validate_required(@attrs)
end
def handle_polymorphic(ch, nil), do: ch
def handle_polymorphic(ch, %type{id: id}) do
ch
|> put_change(:pictureable_type, type)
|> put_change(:pictureable_id, id)
end