Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save iqbalhasnan/24905170bdfd182cd631 to your computer and use it in GitHub Desktop.
Save iqbalhasnan/24905170bdfd182cd631 to your computer and use it in GitHub Desktop.
Rails 4 : Multiple file upload with carrierwave, nested form and jquery file upload - iqbal hasnan http://reka.co https://u.osu.edu/hasnan.1/2014/03/30/rails-4-multiple-file-upload-with-carrierwave-nested-form-and-jquery-file-upload/
<input id="photos_ids" name="photos" type="hidden" value="">
<input data-url="/photos" id="album_upload" multiple="multiple" name="images[]" type="file" ></input>
class Album < ActiveRecord::Base
# belongs to user model
belongs_to :user
# Album has many photos
has_many :photos, :inverse_of => :album, :dependent => :destroy
# enable nested attributes for photos through album class
accepts_nested_attributes_for :photos, allow_destroy: true
end
class AlbumsController < ApplicationController
# truncated for brevity.
def create
@album = current_user.albums.build(album_params)
@album.photos << Photo.find(params[:photos].split(","))
authorize @album
if @album.save
flash[:notice] = "Your album has been created."
redirect_to @album
else
flash[:alert] = "Something went wrong."
render :new
end
end
def album_params
params.require(:album).permit(:title, :description, :photos_attributes => [:album_id, :image])
end
end
$(function(){
var ids = [];
$('#album_upload').fileupload({
done: function (e, data) {
ids.push(data.result.picture_id);
$('#photos_ids').val(ids);
}
});
});
class Photo < ActiveRecord::Base
#photo belongs to album
belongs_to :album
#validations
validates :album, presence: true
# Photo uploader using carrierwave
mount_uploader :image, PhotoUploader
def to_jq_upload
{
"url" => image.medium.url,
"delete_url" => id,
"picture_id" => id,
"delete_type" => "DELETE"
}.to_json
end
end
class PhotosController < ApplicationController
# truncated for brevity.
def create
params[:images].each{ |image|
@photo = Photo.create(image: image)
if @photo.save
respond_to do |format|
format.html { render json: @photo.to_jq_upload, content_type: 'text/html', layout: false }
format.json { render json: @photo.to_jq_upload }
end
else
render json: { error: @photo.errors.full_messages }, status: 304
end
}
end
end
This gist is the update of this post https://u.osu.edu/hasnan.1/2014/03/30/rails-4-multiple-file-upload-with-carrierwave-nested-form-and-jquery-file-upload/
License MIT
@abbirdboy
Copy link

Hi, I've been using this code as the base plate for the album/photo upload segment of my project. At the moment I have an ajax form made with the simple_form (form for) gem for the album attributes (title and description) and then a 'nested' div that is tied to the Ajax file uploader Dropzone.js. When the submit button is clicked, two POST requests are sent, one to the album_controller from simple_form and the other to the photo_controller from the dropzone js. I suppose this might be similar to if I was using Jquery Upload. I'm a bit lost on how to properly implement a nested form where I am able to create an album and upload pictures at the same time. For example, how would the full view form look like, I see that on your form, there's only two input lines.

Thank you!

@iqbalhasnan
Copy link
Author

@abbirdboy , if you want to create and upload photo at the same time, you will only need album controller.

in your album model make sure you have accepts_nested_attributes_for :photos, allow_destroy: true

and update your albums_controller to something like this

  def create
    @album = current_user.albums.build(album_params)
     params[:images].each do |image|
       photo = Photo.create(image: image)
       photo.save
     end
    if @album.save
      flash[:notice] = "Your album has been created."
      redirect_to @album
    else 
      flash[:alert] = "Something went wrong."
      render :new
    end
  end

and your form looks something like

<%= file_field_tag "album[images][]", type: :file, multiple: true %>

@abbirdboy
Copy link

Thank you! I was able to get it to work!

@aalvrz
Copy link

aalvrz commented Oct 8, 2015

Why aren't you using fields_for in your view if you are using nested attributes?

Also, can you please share your album_params method when using only the Albums controller?

Thank you.

@iqbalhasnan
Copy link
Author

@BigChief45 update with album_params

@fabOnReact
Copy link

Hello,
sorry, but I got stuck. I don't understand why we don't use <%= form.file_field :avatars, multiple: true %> for the _form.html.erb as described in https://github.com/carrierwaveuploader/carrierwave#multiple-file-uploads
Additionally should I render _form.html.erb in my user#new or in some other action? then the _form.html.erb triggers the function from album_upload.js, for the image preview, but It is not clear to me how the create action gets called from the submit button.
Sorry I am totally new to carrierwave!

@iqbalhasnan
Copy link
Author

hey @fabriziobertoglio1987,

1 ) you can use <%= form.file_field :avatars, multiple: true %> , but make sure you updated album_upload.js selector accordingly.

2 ) you should render the form in new and edit if there's any.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment