Search code examples
ruby-on-railsdevise

Multiple image upload using nested forms in rails 4


I am working on a project where a devise user uploads many images. So what I'm what trying to achieve is the user uploads an image with a description and then can click on a button "add another" which allows the user to add another image and description, the user can add as many images as they want.

Can someone point me in the right direction in what I'm supposed to look into to achieve the task?


Solution

  • You'll want to use accepts_nested_attributes_for, the standard functionality for including nested attributes in a submission:

    #app/models/project.rb
    class Project < ActiveRecord::Base
       has_many :images
       accepts_nested_attributes_for :images, reject_if: :all_blank, allow_destroy: true
    end
    

    Whilst - strictly speaking - the functionality you want is to add multiple elements to a submission (images#new), Rails can only deal with one record creation at a time. Using the following will be far more beneficial:

    #config/routes.rb
    resources :projects #-> url.com/projects/:id/edit
    
    #app/controllers/projects_controller.rb
    class ProjectsController < ApplicationController
    
       def new
          @project = Project.new
          @project.images.build
       end
    
       def edit
          @project = Project.find params[:id]
       end
    
       def update
          @project = Project.find params[:id]
          @project.update project_params
       end
    
       private
    
       def project_params
         params.require(:project).permit(:x, :y, images_attributes: [:attachment])
       end
    end
    
    #app/views/projects/new.html.erb
    <%= render "form", locals: { project: @project } %>
    
    #app/views/projects/edit.html.erb
    <%= render "form", locals: { project: @project } %>
    
    #app/views/projects/_form.html.erb
    <%= form_for project do |f| %>
       <%= f.text_field :x %>
       <%= f.text_field :y %>
       <%= f.fields_for :images do |i| %>
          <% if i.object.new_record? %>
            <%= f.file_field :attachment %>
          <% else %>
            <%= image_tag i.object.attachment.url %>
            <%= i.check_box :_destroy %>          
          <% end %>
       <% end %>
       <%= f.submit %>
    <% end %>    
    

    The above should give you a form for a @project, with embedded images inside.


    To add "extra" fields, you'll be best looking at the cocoon gem or this Railscast: Nested Forms part 1