Uploading multiple files at once to Rails app with

2019-02-03 22:23发布

问题:

I'm close...very close...I'm able to upload single files just fine...but when i change the type of my form's file_field to :multiple => true so I can upload multiple images at once my uploaded files get wrapped in an array...and the 'magic' of 'accepts_nested_attributes_for` is lost.

Edit: After more examination I wonder if I even need to bother with accepts_nested_attributes_for? Perhaps I should just have a file_field, :multiple => true in my Gallery form (as opposed to a nested form) and then in my create action create the new gallery and then loop through each element in the params[:gallery][:photos_attributes]["0"][:image] array by hand, so to speak, calling @gallery.photos.create for each element. ?!? Seems cumbersome...but it's all I can come up with.

Hoping someone with more experience with Rails can chime in...

Params:

{"utf8"=>"✓", 
"authenticity_token"=>"9jXvIwcllct7UyUfo6cvhEucQf2u3SY50SuaCLtFO4c=", 
"gallery"=>{
  "name"=>"First Gallery", 
  "photos_attributes"=>{"0"=>{
    "image"=>[
      #<ActionDispatch::Http::UploadedFile:0x00000104b78978 
        @original_filename="first_test_image.jpg", 
        @content_type="image/jpeg", 
        @headers="Content-Disposition: form-data; name=\"gallery[photos_attributes][0][image][]\"; filename=\"first_test_image.jpg\"\r\nContent-Type: image/jpeg\r\n", 
        @tempfile=#<File:/var/folders/bQ/bQYZC2ukFZCvbKzEDGRtJE+++TI/-Tmp-/RackMultipart20110622-4459-vz78ee>>, 
      #<ActionDispatch::Http::UploadedFile:0x00000104b78950 
        @original_filename="second_test_image.jpg", 
        @content_type="image/jpeg", 
        @headers="Content-Disposition: form-data; name=\"gallery[photos_attributes][0][image][]\"; filename=\"second_test_image.jpg\"\r\nContent-Type: image/jpeg\r\n", 
        @tempfile=#<File:/var/folders/bQ/bQYZC2ukFZCvbKzEDGRtJE+++TI/-Tmp-/RackMultipart20110622-4459-1jzhhyg>>
      ]
    }
  }
}, "commit"=>"Save", "action"=>"create", "controller"=>"galleries"}



#app/models/gallery.rb 
class Gallery < ActiveRecord::Base 
  has_many :photos, :dependent => :destroy 
  accepts_nested_attributes_for :photos 
end 

#app/models/photo.rb 
class Photo < ActiveRecord::Base 
  belongs_to :gallery 
  mount_uploader :photo, PhotoUploader 
end 

#config/routes.rb
resources :galleries do
  resources :photo, :only => [:create, :destroy]
end

GalleriesController

  def new
    @gallery = Gallery.new
    @gallery.photos.build

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @gallery }
    end
  end

  ...

  def create
    @gallery = Gallery.new(params[:gallery])

    respond_to do |format|
      if @gallery.save
        format.html { redirect_to @gallery, notice: 'Gallery was successfully created.' }
        format.json { render json: @gallery, status: :created, location: @gallery }
      else
        format.html { render action: "new" }
        format.json { render json: @gallery.errors, status: :unprocessable_entity }
      end
    end
  end

回答1:

You can do a little hack for the params array, something like:

aux = []
params[:gallery][:photos_attributes][:image].each do |f|
  aux << {:image => f}
end
params[:post][:photos_attributes] = aux

@gallery = Gallery.new(params[:gallery])

I have a similar problem, I know it's an ugly hack, but it works for me.



回答2:

Ditch accepts_nested_attributes_for and instead add this to your Gallery model.

def photos=(attrs)
  attrs.each { |attr| self.photos.build(:image => attr) }
end

Also, make sure that photos is in your gallery's accessible attribs in case you're protecting against mass assignment. Otherwise you won't get the photos array hash assignment from your params. I.e.

attr_accessible :field1, field2, :photos