Rails 5.2带有Cocoon表单的主动存储 [英] Rails 5.2 Active Storage with Cocoon forms
问题描述
我想使用带有Active Storage的动态茧形表单将一些图像保存到模型中以处理文件.
I want to save some images to a model using a dynamic cocoon form with Active Storage to handle the files.
我有一个农民类,其中有很多苹果,农民可以通过农民表格为每种不同类型的苹果添加多个图像.
I have a farmer class that has many apples, the farmer can add multiple images for each of the different kinds of apples through the farmer form.
class Farmer < ActiveRecord::Base
has_many :apples, inverse_of: :farmer
accepts_nested_attributes_for :apples, allow_destroy: true,
reject_if: :all_blank
end
class Apple < ActiveRecord::Base
has_many_attached :apple_images
end
我在农夫控制器内:
class Farmer < ApplicationController
def update
@farmer = Farmer.find(params[:farmer_id])
if @farmer.valid?
@farmer.update!(farmer_params)
redirect_to edit_farmer_path(farmer_id: @farmer.id)
else
...
...
end
end
private
def farmer_params
params.require(:farmer).permit(
:farmer_name,
apples_attributes: [
:id,
:color,
:size,
:_destroy
])
end
end
我的看法是我刚刚将其添加到我的茧字段
my view I just added this to my cocoon fields
<div class="form-field">
<%= f.label :apple_images, "Please upload apple images" %>
<%= f.file_field :apple_images, multiple: true, data: { validates: {required: {}} } %>
</div>
现在,一旦保存了农夫对象,茧就将使用accepts_nested_attributes_for
调用来保存苹果属性.一切正常,直到我尝试将apple_images
添加到表单中.
Now cocoon will save the apple attributes using the accepts_nested_attributes_for
call once the farmer object is saved. This is all working just fine until I tried adding the apple_images
to the form.
阅读Active Storage自述文件我发现它建议您在保存项目后立即附加文件.
Reading up on the Active Storage readme I see it suggests you should attach the files right after the item has been saved.
您可以在此处阅读自述文件
但是简而言之,如果您想在控制器中使用单个图像,请执行以下操作:
but in short if you want a single image in the controller do this:
#inside an update method
Current.user.avatar.attach(params.require(:avatar))
或者如果您想要多张图像:
or if you want multiple images:
def create
message = Message.create! params.require(:message).permit(:title, :content)
message.images.attach(params[:message][:images])
redirect_to message
end
当图像直接位于我要保存在控制器中的模型上时,这似乎很简单.
This seems fairly simple when the image is directly on the model I am saving within the controller.
起初,我认为这就像将apple_images添加到参数中一样简单:
At first, I thought it may be just as easy as adding apple_images to the params like so:
def farmer_params
params.require(:farmer).permit(
:farmer_name,
apples_attributes: [
:id,
:color,
:size,
:apple_images,
:_destroy
])
end
但这将返回错误:
ActiveModel::UnknownAttributeError - unknown attribute 'apple_images' for Apple.:
我正在考虑在更新/创建apple对象之后,在apple模型上使用after_save回调来附加图像.尽管我也不确定如何实现这一目标.
I am thinking about using an after_save callback on the apple model to attach the images after the apple object is updated / created. Although I am not sure how to achieve this either.
感到有点迷茫,任何想法或建议将不胜感激
Feeling a little lost, any ideas or suggestions will be greatly appreciated
编辑
这是更新时参数的样子:
This is what the params look like at the time of update:
<ActionController::Parameters {"utf8"=>"✓", "_method"=>"patch",
"farmer"=>{"farmer_name"=>"billy the farmer", "apples_attributes"=>
{"0"=>{"color"=>"Green",
"size"=>"A",
"apple_images"=>[#<ActionDispatch::Http::UploadedFile:0x007f9e8aa93168 @tempfile=#<Tempfile:/var/folders/n7/65r5561n44q0w4bdnmw42l880000gn/T/RackMultipart20171211-87415-1m2w7gh.png>, @original_filename="Screen Shot 2017-12-07 at 09.13.28.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"farmer[apples_attributes][0][apple_images][]\"; filename=\"Screen Shot 2017-12-07 at 09.13.28.png\"\r\nContent-Type: image/png\r\n">,
#<ActionDispatch::Http::UploadedFile:0x007f9e8aa93118 @tempfile=#<Tempfile:/var/folders/n7/65r5561n44q0w4bdnmw42l880000gn/T/RackMultipart20171211-87415-1gdbax2.jpeg>, @original_filename="WhatsApp Image 2017-12-06 at 1.23.35 PM.jpeg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"farmer[apples_attributes][0][apple_images][]\"; filename=\"WhatsApp Image 2017-12-06 at 1.23.35 PM.jpeg\"\r\nContent-Type: image/jpeg\r\n">],
"_destroy"=>"false", "id"=>"4"}}},
"commit"=>"Next",
"controller"=>"farmer/produce",
"action"=>"update",
"farmer_id"=>"3"} permitted: false>
推荐答案
您应从farmer_params
中删除apple_images
(因为它不是Apple
的已知属性).但是删除该位置将确保不保存图像.但是,这就是它的工作方式(有点怪异的恕我直言).
You should remove the apple_images
from the farmer_params
(because it is not a known attribute of Apple
). But removing that will make sure the images are not saved. This is however, how it is intended to work (a bit weird imho).
如果您查看文档,他们将显式忽略images
属性,并将其单独设置:
If you check the documentation they explicitly ignore the images
attribute and set it separately:
message = Message.create! params.require(:message).permit(:title, :content)
message.images.attach(params[:message][:images])
我不确定您应如何在嵌套表单设置中解决此问题.您可以遍历参数中的所有苹果并尝试设置apple_images
,但这似乎很容易出错(如何将没有id的新苹果与保存的苹果匹配?).
I am not entirely sure how you should solve this in a nested form setting. You could iterate over all apples in the params and try to set the apple_images
but that seems very error-prone (how do you match a new apple without id to the one that is saved?).
您可以尝试如下添加方法(并将apple_images
保留在允许的参数中):
You could try adding a method as follows (and keep the apple_images
in the permitted params):
def apple_images=(images)
self.apple_images.attach(images)
end
但不确定在保存apple
之前是否可行.
But not sure if that works before the apple
is saved.
这篇关于Rails 5.2带有Cocoon表单的主动存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!