【问题标题】:Ecto Changeset allowing a virtual association during the changeset isn't working允许在变更集期间进行虚拟关联的 Ecto 变更集不起作用
【发布时间】:2018-05-16 11:01:41
【问题描述】:

我想要一个虚拟关联,这样我就可以做多态关联。所以我有一个图片模式,它与用户(和其他人)有关。我将在回调中有一个位置,我将多态类型/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} 之类的属性创建图片,该属性将转换为 %{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) 测试,结构不是地图似乎也存在一些问题。知道为什么它被视为不是地图吗?

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    我最初的倾向是根本不投射图片,因为您真的不希望 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多