Rails 4 : Multiple file upload with carrierwave, nested form and jquery file upload

In this example, I will show you how to allow a single form submission from a parent object with multiple children associate to it using the “nested form”.

1) Let say we have a schema for albums that has many photos associate to it.

  
create_table "albums", force: true do |t|
    t.string   "title",       null: false
    t.text     "description"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end
  
create_table "photos", force: true do |t|
    t.integer  "album_id"
    t.string   "image"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

2) Create new carrierwave uploader. see this post in order to setup one https://iqbalhasnan.wordpress.com/2014/03/13/rails-4-upload-image-to-s3-using-fog-and-carrierwave/

3) Our Albums and Photos models.

class Album  :album, :dependent => :destroy
	# enable nested attributes for photos through album class
	accepts_nested_attributes_for :photos, allow_destroy: true
end
class Photo < ActiveRecord::Base
        #photo belongs to album
	belongs_to	:album
	#validations
	validates 	:album, presence: true
	# Photo uploader using carrierwave
        mount_uploader :image, PhotoUploader
end

4) Our Controller where all the magic happens

In our case, we want to allow our user to upload multiple photos, and it will only get saved when user hits the submit button. User will be able to add more images in the future when they click edit album and add images from there.

So here is the album controller.

class AlbumsController < ApplicationController
# truncated for brevity.
  def create
    @album = current_user.albums.build(album_params)
    authorize @album
    if @album.save
      # to handle multiple images upload on create
      if params[:images]
        params[:images].each { |image|
          @album.photos.create(image: image)
        }
      end
      flash[:notice] = "Your album has been created."
      redirect_to @album
    else 
      flash[:alert] = "Something went wrong."
      render :new
    end
  end
  def update
    authorize @album
    if @album.update(params[:album].permit(:title,:description))
      # to handle multiple images upload on update when user add more picture
      if params[:images]
        params[:images].each { |image|
          @album.photos.create(image: image)
        }
      end
      flash[:notice] = "Album has been updated."
      redirect_to @album
    else
      render :edit
    end
  end
end

 


Photos controller:

class PhotosController < ApplicationController
# truncated for brevity.
  def create
    @photo = Photo.new(photo_params)
    @photo.save
  end
end

5) Our Views

In this example, we are not using nested resources. That means we have our routes to setup like this
config/routes.rb

resources :albums
resources :photos

app/views/albums/_form.html.erb

  {:multipart => true} do |f| %>

‘control-label’ %>

‘text_field’ %>

‘control-label’ %>

‘text_field’ %>
#images[] returned to the album as an array. We use file_field_tag since images is not @album’s attribute
“btn btn-default” %>

pay attention to the comment that I made on _form.html.erb template.

6) Handle image preview with jquery file upload
I’m not going to cover this topic at this time.

So, that’s it. now when your user hit the submit button, rails will save all the images to album.

http://www.reka.co

http://www.rekabrand.com

6 thoughts on “Rails 4 : Multiple file upload with carrierwave, nested form and jquery file upload

  1. Hey thanks so much for that, did you ever get around to adding Jquery file upload to this? I’ve been tinkering in my app trying to get it to work but am unable to do so.

  2. If I try to use

    in a form_for, I would not be getting the Action::Dispatch objects for the images, instead I would simply get
    “post”=>{“post_attachments_attributes”=>[{“image”=>”Honeycrisp-Apple.jpg”}]}
    Any reason for that?

Leave a comment