Winston Kotzan
Winston Kotzan

Reputation: 2087

Rails file_field_tag with multiple files delivers random string to controller

I am building a form to accept multiple images. Here's the form in Slim

  = form_tag(product_images_path(product_id: product.id), multipart: true, remote: true) do
    label Add Image
    = file_field_tag(:attachment, multiple: true, name: 'image[attachment]', direct_upload: true, class: 'drop-target')
    = submit_tag 'Upload'

When I test this form and attach a file and the data hits the controller, the attachment turns into some kind of random string instead of an array of ActionDispatch::Http::UploadedFile as I would expect. Here's the result of checking params in console:

<ActionController::Parameters {
  "utf8"=>"✓",
  "authenticity_token"=>"....", 
  "image"=>{"attachment"=>"eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBOQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--79ca56f5342586a657d079d36e45f769dacc9356"},
  "commit"=>"Upload", 
  "controller"=>"rics_channels/admin/images", 
  "action"=>"create", 
  "product_id"=>"5355"} 
permitted: false>

I can't figure out how to properly format/process the image[attachment]'s. See anything I'm doing wrong?

Upvotes: 4

Views: 2729

Answers (2)

Winston Kotzan
Winston Kotzan

Reputation: 2087

I discovered that the problem was that my file_field_tag needed an extra [] in the name.

= file_field_tag('attachment[images][]', multiple: true, class: 'drop-target')

Then in the controller:

params[:attachment][:images]
#=>[#<ActionDispatch::Http::UploadedFile:0x00007f8a70185a90
  @content_type="image/jpeg",
  @headers="Content-Disposition: form-data; name=\"attachment[images][]\"; filename=\"image1.jpg\"\r\nContent-Type: image/jpeg\r\n",
  @original_filename="image.jpg",
  @tempfile=#<File:/var/folders/p6/dshxxfqj6lq83t652t6j59ym0000gn/T/RackMultipart20180703-9499-9rs1km.jpg>>,
 #<ActionDispatch::Http::UploadedFile:0x00007f8a70a0bac0
  @content_type="image/jpeg",
  @headers="Content-Disposition: form-data; name=\"attachment[images][]\"; filename=\"image2.jpg\"\r\nContent-Type: image/jpeg\r\n",
  @original_filename="image2.jpg",
  @tempfile=#<File:/var/folders/p6/dshxxfqj6lq83t652t6j59ym0000gn/T/RackMultipart20180703-9499-wfuqs.jpg>>,
 #<ActionDispatch::Http::UploadedFile:0x00007f8a6dc82338
  @content_type="image/jpeg",
  @headers="Content-Disposition: form-data; name=\"attachment[images][]\"; filename=\"image3.jpg\"\r\nContent-Type: image/jpeg\r\n",
  @original_filename="image.jpg",
  @tempfile=#<File:/var/folders/p6/dshxxfqj6lq83t652t6j59ym0000gn/T/RackMultipart20180703-9499-9oe8y4.jpg>>]

Upvotes: 2

George Claghorn
George Claghorn

Reputation: 26535

You’re using direct uploads (note that direct_upload: true is passed to file_field_tag). When the form is submitted, Active Storage’s JavaScript uploads the file directly to your storage service, bypassing your app. In lieu of the actual file, the app receives a signed blob ID.

You can pass this signed blob ID to attach (here I assume file is the name of your attachment):

image.file.attach(params[:image][:attachment])

…or use it to instantiate a new record:

image = Image.new(file: params[:image][:attachment])

Active Storage uses the signed blob ID to look up the corresponding blob and attach it to your record.

Upvotes: 1

Related Questions