Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 multiple image or file upload using carrierwave

How can I upload multiple images from a file selection window using Rails 4 and CarrierWave? I have a post_controller and post_attachments model. How can I do this?

Can someone provide an example? Is there a simple approach to this?

like image 715
SSR Avatar asked Jan 28 '14 17:01

SSR


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

Or you can find working demo : Multiple Attachment Rails 4

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 generate scaffold post title:string 

Create post_attachment scaffold

rails generate 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)        end        format.html { redirect_to @post, notice: 'Post was successfully created.' }      else        format.html { render action: 'new' }      end    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 %>     <div class="actions">      <%= f.submit %>    </div> <% end %> 

To edit an attachment and list of attachment for any post. 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 %>   <%= link_to "Edit Attachment", edit_post_attachment_path(p) %> <% end %>  <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %> 

Update form to edit an attachment views/post_attachments/_form.html.erb

<%= image_tag @post_attachment.avatar %> <%= form_for(@post_attachment) do |f| %>   <div class="field">     <%= f.label :avatar %><br>     <%= f.file_field :avatar %>   </div>   <div class="actions">     <%= f.submit %>   </div> <% end %> 

Modify update method in post_attachment_controller.rb

def update   respond_to do |format|     if @post_attachment.update(post_attachment_params)       format.html { redirect_to @post_attachment.post, notice: 'Post attachment was successfully updated.' }     end    end end 

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.

For edit an attachment we cant modify all the attachments at a time. so we will replace attachment one by one, or you can modify as per your rule, Here I just show you how to update any attachment.

like image 185
SSR Avatar answered Oct 13 '22 05:10

SSR


If we take a look at CarrierWave's documentation, this is actually very easy now.

https://github.com/carrierwaveuploader/carrierwave/blob/master/README.md#multiple-file-uploads

I will use Product as the model I want to add the pictures, as an example.

  1. Get the master branch Carrierwave and add it to your Gemfile:

    gem 'carrierwave', github:'carrierwaveuploader/carrierwave' 
  2. Create a column in the intended model to host an array of images:

    rails generate migration AddPicturesToProducts pictures:json 
  3. Run the migration

    bundle exec rake db:migrate 
  4. Add pictures to model Product

    app/models/product.rb  class Product < ActiveRecord::Base   validates :name, presence: true   mount_uploaders :pictures, PictureUploader end 
  5. Add pictures to strong params in ProductsController

    app/controllers/products_controller.rb  def product_params   params.require(:product).permit(:name, pictures: []) end 
  6. Allow your form to accept multiple pictures

    app/views/products/new.html.erb  # notice 'html: { multipart: true }' <%= form_for @product, html: { multipart: true } do |f| %>   <%= f.label :name %>   <%= f.text_field :name %>    # notice 'multiple: true'   <%= f.label :pictures %>   <%= f.file_field :pictures, multiple: true, accept: "image/jpeg, image/jpg, image/gif, image/png" %>    <%= f.submit "Submit" %> <% end %> 
  7. In your views, you can reference the images parsing the pictures array:

    @product.pictures[1].url 

If you choose several images from a folder, the order will be the exact order you are taking them from top to bottom.

like image 32
drjorgepolanco Avatar answered Oct 13 '22 06:10

drjorgepolanco