How to: Add more files and remove single file when using default multiple file uploads feature

Bob Cao edited this page Dec 31, 2015 · 1 revision

You could use PostgreSQL array to implement such a feature. To be specific, in your migration, you could write

class AddImagesToGallery < ActiveRecord::Migration
  def change
    add_column :galleries, :images, :string, array: true, default: [] # add images column as array
  end
end

In your view, you could do this

.field 
  = f.file_field :images, multiple: true # make this input a multiple files input  

In your controller, you could allow nested params in the following way

def gallery_params
  params.require(:gallery).permit(:title, {images: []}) # allow nested params as array
end

When you want to implement add more and remove single image feature, you could write your routes in the following way

Rails.application.routes.draw do
  resources :galleries do
    resources :images, :only => [:create, :destroy] # support #create and #destroy
  end
end

So that you could implement your views in the following way

h1 Add more images

= form_for @gallery, url: gallery_images_path(@gallery), method: :post do |f| # use customized url endpoint 
  .field
    = f.file_field :images, multiple: true

  .actions = f.submit "Add More Images"

And

div
  - @gallery.images.each_with_index do |image, index| #grab the index
    div 
      = image_tag(image.url)
      = link_to "Delete", gallery_image_path(@gallery, index), :method => :delete, data: { confirm: "Are you sure you want to delete this image?" }

So that you could implement your image controller in the following way

class ImagesController < ApplicationController
  before_action :set_gallery

  def create
    add_more_images(images_params[:images])
    flash[:error] = "Failed uploading images" unless @gallery.save
    redirect_to :back
  end

  def destroy
    remove_image_at_index(params[:id].to_i)
    flash[:error] = "Failed deleting image" unless @gallery.save
    redirect_to :back
  end

  private

  def set_gallery
    @gallery = Gallery.find(params[:gallery_id])
  end

  def add_more_images(new_images)
    images = @gallery.images 
    images += new_images
    @gallery.images = images
  end

  def remove_image_at_index(index)
    remain_images = @gallery.images # copy the array
    deleted_image = remain_images.delete_at(index) # delete the target image
    deleted_image.try(:remove!) # delete image from S3
    @gallery.images = remain_images # re-assign back
  end

  def images_params
    params.require(:gallery).permit({images: []}) # allow nested params as array
  end
end

For more detailed step by step walkthrough, please refer to Multiple Images Uploading With CarrierWave and PostgreSQL Array

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.