Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uploading multiple files at once to Rails app with Carrierwave (HTML5)

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
like image 662
Meltemi Avatar asked Jun 22 '11 22:06

Meltemi


2 Answers

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.

like image 84
Jonathan Hernández Avatar answered Oct 25 '22 00:10

Jonathan Hernández


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
like image 2
Dave Rapin Avatar answered Oct 25 '22 00:10

Dave Rapin