Ecto:将 %Plug.Upload 投射到虚拟字段以进行文件上传验证

Aar*_*all 5 elixir ecto phoenix-framework

我希望仅当变更集有效并包含文件时才能够触发文件上传。

是否有可能/一个好主意,%Plug.Upload例如投射

def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
    |> save_image
end

defp save_image(changeset) do
  case changeset do 
    %Ecto.Changeset{valid?: true, changes: %{image: image}} ->
      %{ "url" => "http://" <> image_url } = Cloudinary.upload(image)
      put_change(changeset, :image_url, image_url)
    _ -> 
     changeset
 end
end
Run Code Online (Sandbox Code Playgroud)

我试图设置:image为类型的虚拟字段,:map但它不会投射` %Plug.Upload

schema "model" do
  field :image_url, :string
  field :image, :map, virtual: true
  timestamps
end
Run Code Online (Sandbox Code Playgroud)

这只会导致消息验证错误 Image is invalid

Gaz*_*ler 5

为什么不定义以下函数(在单独的模块中):

def save_image(model, params) do
  changeset = Model.changeset(model, params)
  case changeset.valid? do
    true ->
      %{ "url" => "http://" <> image_url } = Cloudinary.upload(params["file"])
      Model.image_changeset(changeset, image)
    _ -> changeset
  end
end
Run Code Online (Sandbox Code Playgroud)

并在您的模型中为图像变更集提供一个单独的功能。

def image_changeset(changeset, image_url) do
  put_change(changeset, :image_url, image_url)
end
Run Code Online (Sandbox Code Playgroud)


Aar*_*all 4

只需将虚拟字段的类型设置为:any

schema "model" do
  field :image_url, :string
  field :image, :any, virtual: true
  timestamps
end
Run Code Online (Sandbox Code Playgroud)

现在,当所有必填字段都存在并且有一个文件时,它会将其上传到云端,否则,如果没有选择图像文件,它将照常创建/更新字段,而不会触发上传