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
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With