Rails 5.2带有Cocoon表单的主动存储 [英] Rails 5.2 Active Storage with Cocoon forms

查看:90
本文介绍了Rails 5.2带有Cocoon表单的主动存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用带有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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆