This post shows how to use carrierwave gem to upload multiple files in Rails 4
Let suppose the following scenario. We have multiple projects and each project can have multiple screenshots.
In project.rb
class Project < ActiveRecord::Base has_many :screenshots accepts_nested_attributes_for :screenshots, :allow_destroy => true end
In screenshot.rb
class Screenshot < ActiveRecord::Base belongs_to :project mount_uploader :image, ScreenshotUploader end
In project_controller.rb
class ProjectsController < ApplicationController # GET /projects/new def new @project = Project.new @project.screenshots.new end # GET /projects/1/edit def edit @project.screenshots.new end # POST /projects # POST /projects.json def create @project = Project.new(project_params) respond_to do |format| if @project.save if params[:screenshots_attributes] params[:screenshots_attributes].each do |screenshot| @project.screenshots.create(image: screenshot[:image]) end end format.html { redirect_to @project, notice: 'Project was successfully created.' } format.json { render :show, status: :created, location: @project } else format.html { render :new } format.json { render json: @project.errors, status: :unprocessable_entity } end end end # PATCH/PUT /projects/1 # PATCH/PUT /projects/1.json def update respond_to do |format| if @project.update(project_params) if params[:screenshots_attributes] params[:screenshots_attributes].each do |screenshot| @project.screenshots.create(image: screenshot[:image]) end end format.html { redirect_to @project, notice: 'Project was successfully updated.' } format.json { render :show, status: :ok, location: @project } else format.html { render :edit } format.json { render json: @project.errors, status: :unprocessable_entity } end end end # DELETE /projects/1 # DELETE /projects/1.json def destroy @project.destroy respond_to do |format| format.html { redirect_to projects_url, notice: 'Project was successfully destroyed.' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_project @project = Project.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def project_params params.require(:project).permit(:title, :description, :screenshots_attributes => [:image]) end end
In views/projects/_forms.html.erb
<%= form_for @project, :html => {:multipart => true, :class => "form-horizontal project" } do |f| %> <div class="form-group"> <%= f.label :title, :class => 'col-sm-2 control-label' %> <div class="col-sm-10"> <%= f.text_field :title, :class => 'form-control' %> </div> <%= error_span(@project[:title]) %> </div> <div class="form-group"> <%= f.label :description, :class => 'col-sm-2 control-label' %> <div class="col-sm-10"> <%= f.text_area :description, :class => 'form-control' %> </div> <%= error_span(@project[:description]) %> </div> <div class="form-group"> <%= f.fields_for :screenshots, @project.screenshots do |f_screenshot| %> <%= f_screenshot.label :image, :class => 'col-sm-2 control-label' do %> Screenshots <% end %> <div class="col-sm-10"> <%= f_screenshot.file_field :image, multiple: true, :name=>'project[screenshots_attributes][]', :class => 'form-control' %> </div> <% end %> </div> <div class="form-actions"> <%= f.submit nil, :class => 'btn btn-primary' %> <%= link_to t('.cancel', :default => t("helpers.links.cancel")), projects_path, :class => 'btn btn-default' %> </div> <% end %>
Reference: Stackoverflow
2 Comments
Nice post. How would you write a destroy action for uploaded images and provide a delete link under images using link_to ?
I’m using refile gem which works kinda same way as carrier wave but you don’t need to modify the controller. But i need to write a destroy action to remove the images
Practical post ! Coincidentally , if anyone have been needing to merge PDF or PNG files , my business encountered a tool here
https://goo.gl/UpwAOj
.