Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Carrierwave, Rails 4, and Multiple Uploads

I have been banging my head against the wall trying to get Carrierwave, Rails 4, and Multiple Uploads all working together. I can get a single file upload working just fine as in this and many other projects.

This is not a nested situation - just simply uploading to a single model called Transcription and wanting to create a record for each document uploaded.

I cannot seem to find the correct way to declare the "document" field used for the carrierwave mount

mount_uploader :document, DocumentUploader

as an array for the strong parameters to recognize.

I have tried whitelisting: whitelisted[:document] = params[:transcription]['document'],

declaring the "document" as an array:

params.require(:transcription).permit(..... ,:document => [])

params.require(:transcription).permit(..... , { document: [] })

This all seems more like I am declaring the array for a nested model, but I really want Rails 4's strong parameters to simply see the "document" array created by the file_field, :multiple => true

ie. from the log: form-data; name=\"transcription[document][]

Has anybody successfully accomplished multiple uploads in Rails 4 with strong parameters? If so would you please share?

Thanks...

Cheers,

Bill

like image 426
Bill Kiskin Avatar asked Oct 31 '13 17:10

Bill Kiskin


People also ask

How do I upload multiple images in rails?

A file can be uploaded to server in two ways, one we can send the image as base64 string as plain text and another one is using multipart/form-data . The first one is the worst idea as it sends the entire image as plain text.


2 Answers

This is solution to upload multiple images using carrierwave in rails 4 from scratch

To do just follow these steps.

rails new multiple_image_upload_carrierwave

In gem file

gem 'carrierwave'
bundle install
rails generate uploader Avatar 

Create post scaffold

rails g scaffold post title:string

Create post_attachment scaffold

rails g scaffold post_attachment post_id:integer avatar:string

rake db:migrate

In post.rb

class Post < ActiveRecord::Base
   has_many :post_attachments
   accepts_nested_attributes_for :post_attachments
end

In post_attachment.rb

class PostAttachment < ActiveRecord::Base
   mount_uploader :avatar, AvatarUploader
   belongs_to :post
end

In post_controller.rb

def show
   @post_attachments = @post.post_attachments.all
end

def new
   @post = Post.new
   @post_attachment = @post.post_attachments.build
end

def create
   @post = Post.new(post_params)

   respond_to do |format|
     if @post.save
       params[:post_attachments]['avatar'].each do |a|
          @post_attachment = @post.post_attachments.create!(:avatar => a, :post_id => @post.id)
       end
       format.html { redirect_to @post, notice: 'Post was successfully created.' }
     else
       format.html { render action: 'new' }
     end
   end
 end

 def update
   respond_to do |format|
     if @post.update(post_params)
       params[:post_attachments]['avatar'].each do |a|
         @post_attachment = @post.post_attachments.create!(:avatar => a, :post_id => @post.id)
       end
     end
  end

  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to @post }
      format.json { head :no_content }
    end
  end


 private
   def post_params
      params.require(:post).permit(:title, post_attachments_attributes: [:id, :post_id, :avatar])
   end

In views/posts/_form.html.erb

<%= form_for(@post, :html => { :multipart => true }) do |f| %>
   <div class="field">
     <%= f.label :title %><br>
     <%= f.text_field :title %>
   </div>

   <%= f.fields_for :post_attachments do |p| %>
     <div class="field">
       <%= p.label :avatar %><br>
       <%= p.file_field :avatar, :multiple => true, name: "post_attachments[avatar][]" %>
     </div>
   <% end %>

   <% if params[:controller] == "post" && params[:action] == "edit" %> 
     <% @post.post_attachments.each do |p| %>
       <%= image_tag p.avatar, :size => "150x150" %>
     <% end %>
   <% end %>

   <div class="actions">
     <%= f.submit %>
   </div>
<% end %>

In views/posts/show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Title:</strong>
  <%= @post.title %>
</p>

<% @post_attachments.each do |p| %>
  <%= image_tag p.avatar_url, :size => "150x150" %>
  <%= link_to "Destroy", p, method: :delete %>
<% end %>

<%= link_to 'Edit', edit_post_path(@post) %> |
<%= link_to 'Back', posts_path %>

In rails 3 no need to define strong parameters and as you can define attribute_accessible in both the model and accept_nested_attribute to post model because attribute accessible is deprecated in rails 4.

like image 59
SSR Avatar answered Oct 06 '22 09:10

SSR


CarrierWave doesn't support multiple uploads. It's designed to associate a single file with a single field.

If you want multiple uploads, you need either multiple fields (each with a CarrierWave uploader), or multiple objects each with a single CarrierWave uploader field.

The multiple attribute is also unsupported, so if you use it, it's entirely up to you to get the parameters assigned properly.

like image 26
Taavo Avatar answered Oct 06 '22 08:10

Taavo