Ecto:将 %Plug.Upload 转换为虚拟字段以进行文件上传验证
Ecto: Casting %Plug.Upload to virtual field for file upload validations
我希望仅当变更集有效且包含文件时才能够触发文件上传。
投射 %Plug.Upload
是 possible/A 好主意吗,例如
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
我已尝试将 :image
设置为类型为 :map
的虚拟字段,但它不会强制转换 `%Plug.Upload
schema "model" do
field :image_url, :string
field :image, :map, virtual: true
timestamps
end
这只会导致验证错误并显示消息 Image is invalid
为什么不定义以下函数(在单独的模块中):
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
并且在您的模型中有一个单独的函数专门用于图像变更集。
def image_changeset(changeset, image_url) do
put_change(changeset, :image_url, image_url)
end
只要将虚拟字段的类型设置为 :any
就可以了
schema "model" do
field :image_url, :string
field :image, :any, virtual: true
timestamps
end
现在,当所有必填字段都存在并且有一个文件时,它会将其上传到云端,否则它只会 create/update 正常 create/update 字段,如果没有选择图像文件则不会触发上传
我希望仅当变更集有效且包含文件时才能够触发文件上传。
投射 %Plug.Upload
是 possible/A 好主意吗,例如
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
我已尝试将 :image
设置为类型为 :map
的虚拟字段,但它不会强制转换 `%Plug.Upload
schema "model" do
field :image_url, :string
field :image, :map, virtual: true
timestamps
end
这只会导致验证错误并显示消息 Image is invalid
为什么不定义以下函数(在单独的模块中):
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
并且在您的模型中有一个单独的函数专门用于图像变更集。
def image_changeset(changeset, image_url) do
put_change(changeset, :image_url, image_url)
end
只要将虚拟字段的类型设置为 :any
schema "model" do
field :image_url, :string
field :image, :any, virtual: true
timestamps
end
现在,当所有必填字段都存在并且有一个文件时,它会将其上传到云端,否则它只会 create/update 正常 create/update 字段,如果没有选择图像文件则不会触发上传