0

I'm getting a trouble when I try to use a multi upload file.

this is my form partial view:

<%= simple_form_for @product, :html => { :multipart => true, :class => 'form-horizontal'} do |f| %>
  <%= f.input :name %>
  <%= f.input :description %>
  <%= f.input :price %>
  <%= f.input :isenable, check_box_html: { class: 'check_box' }  %>
  <div class="row-fluid">
    <ul class="thumbnails">
      <%= f.simple_fields_for :attachments do |attachments_form| %>
        <li class="span4">
          <div class="thumbnail">
              <%= image_tag attachments_form.object.image_url(:thumb).to_s if attachments_form.object %>
              <%= attachments_form.label :_destroy, "Borrar Imagen" %>
              <%= attachments_form.file_field :image %>
          </div>
        </li>
      <% end %>
    </ul>
  </div>
  <%= f.button :submit %>
  <%= link_to t('.cancel', :default => t("helpers.links.cancel")),
                products_path, :class => 'btn' %>

<% end %>

This is my controller:

   class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]


  # GET /products
  # GET /products.json
  def index
    @products = Product.all
  end

  # GET /products/list
  # GET /products/list.json
  def list
    @products = Product.all
  end

  # GET /products/1
  # GET /products/1.json
  def show
  end

  # GET /products/new
  def new
    @product = Product.new
    3.times do
        attachments = @product.attachments.build
    end
  end

  # GET /products/1/edit
  def edit
  end

  # POST /products
  # POST /products.json
  def create
    @product = Product.new(product_params)

    respond_to do |format|
      if @product.save
        format.html { redirect_to @product, notice: 'Product was successfully created.' }
        format.json { render action: 'show', status: :created, location: @product }
      else
        format.html { render action: 'new' }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /products/1
  # PATCH/PUT /products/1.json
  def update
    respond_to do |format|
      if @product.update(product_params)
        format.html { redirect_to @product, notice: 'Product was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @product.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /products/1
  # DELETE /products/1.json
  def destroy
    @product.destroy
    respond_to do |format|
      format.html { redirect_to products_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_product
      @product = Product.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def product_params
      params.require(:product).permit(:name, :description, :price, :isenable, attachments_attributes: [:image, :remove_image])
    end
end

And this is the show file:

<%- model_class = Product -%>
<div class="page-header">
  <h1><%=t '.title', :default => model_class.model_name.human.titleize %></h1>
</div>

<dl class="dl-horizontal">
  <dt><strong><%= model_class.human_attribute_name(:name) %>:</strong></dt>
  <dd class="lead"><%= @product.name %></dd>
  <dt><strong><%= model_class.human_attribute_name(:description) %>:</strong></dt>
  <dd class="lead"><%= @product.description %></dd>
  <dt><strong><%= model_class.human_attribute_name(:price) %>:</strong></dt>
  <dd class="lead"><%= @product.price %></dd>
  <dt><dt>
</dl>
<div class="row-fluid">
  <ul class="thumbnails">
    <% @product.attachments.each do |picture| %>
      <li class="span4">
        <div class="thumbnail">
          <%= image_tag picture.image_url(:full).to_s %>
        </div>
      </li>
    <% end %>
  </ul>
</div>
<div class="form-actions">
  <%= link_to t('.back', :default => t("helpers.links.back")),
              products_path, :class => 'btn'  %>
  <%= link_to t('.edit', :default => t("helpers.links.edit")),
              edit_product_path(@product), :class => 'btn' %>
  <%= link_to t('.destroy', :default => t("helpers.links.destroy")),
              product_path(@product),
              :method => 'delete',
              :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
              :class => 'btn btn-danger' %>
</div>

I'm using Rails 4.0.0 ruby 2.0.0p247, as I said I'm using CarrierWave to upload files, in the create screen if I left the image empty it creates an empty image object. what I want is to don't create the image if the user don't add a file. Also another problem that I have is related with the remove link. it simple doesn't work. any suggestion?


I've solved partially the problem adding the following line to my product model:

accepts_nested_attributes_for :attachments, :allow_destroy => true,
                        :reject_if => lambda {
                          |a| a['image'].blank?
                        }

it allows my to don't insert any image if it hasn't file. so part of my problem is already solved what I need to still solve is the fact that remove link doesn't work.

2 Answers 2

1

Ok reviewing the documentation of CarrierWave and principally of Rails documentation I found out the resolution of my problems. The first one as I said before the solution to prevent insert files blank was include in my products model the following line:

accepts_nested_attributes_for :attachments, :allow_destroy => true,
                        :reject_if => lambda {
                          |a| a['image'].blank?
                        }

To solve the problem that CarrierWave doesn't remove the images I found out that when you use nested attributes you should include the :id and :_destroy as permit in your controller like this:

# permit :id and :_destroy

    params.require(:author).permit(:name, books_attributes: [:title, :id, :_destroy])

This is exactly what I did in my controller and also I've changed the name of the checkbox in the view. So in brief the controller was like this:

def product_params
  params.require(:product).permit(:name, :description, :price, :isenable, attachments_attributes: [:image, :_destroy, :id])
end

and the view was in that way:

<label><%= attachments_form.check_box :_destroy %>Borrar Imagen</lable>

Doing that I finally solve both problems, thanks anyway for the help.

Sign up to request clarification or add additional context in comments.

Comments

0

In your create action you have to create the attachment, you have to do something like this ..

  @product.attachments.create(:attachment_id).save

where attachment_id is the id of the attachments attached with the product.

1 Comment

Sorry but I can't undesrtand how this can solve the fact that every time edit my product the collection of attachments has the exactely double of objects (the origial with the images and the same amount of empty objects, what I guess I have to prevent is save attachments with null in the image property but I can't fugured out how. Anyway I'll try what you said and let you know.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.