Dodanie dropzone do istniejącego formularza


#1

Mój stary formularz:
_form.html.erb

<%= simple_form_for [:user, @product] do |f| %>
  <%= f.input :name, label: "Nazwa" %>
  <%= f.input :description, label: "Opis" %>
  <%= f.input :long_description, label: "Długi opis" %>
  <%= f.input :price, label: "Cena" %>
  <%= f.association :category, label: "Kategoria" %>
  <%= f.input :condition, label: "Stan", :collection => [['Nowy','Nowy'],['Używany','Używany']] %>
  <%= f.file_field :photo, :class => "dropzone", multiple: true %>
  <%#= f.submit "Dodaj", :class => "btn btn-success" %>
<%# end %>

product.rb

class Product < ActiveRecord::Base
 mount_uploaders :photo, ProductPhotoUploader
 serialize :photo, JSON
end

products_controller.rb

  class User::ProductsController < User::BaseController

before_action :edit, only: [:show, :edit, :update, :destroy, :product_owner]
#before_action :authenticate_user!,except:[:index]
before_action :authenticate_user!
before_action :product_owner, only: [:edit, :update, :destroy]
#skip_before_action :verify_authenticity_token

def product_owner
 unless @product.user_id == current_user.id
  flash[:danger] = 'Odmowa dostępu, nie jesteś właścicielem tego produktu!'
  redirect_to user_root_path
 end
end

def index
    @q = Product.where(user_id: current_user).ransack(params[:q])
    #@q = Product.ransack(params[:q])
    @products = @q.result(distinct: true).page(params[:page]).per(30)
end

def new
  @product = Product.new
end

def create
  @product = Product.new(product_params)
  @product.user_id = current_user.id
  if @product.save
    redirect_to user_products_path, notice: "Pomyślnie dodano produkt."
  else
    render action: :new
  end


end

def edit
  @product = Product.find(params[:id])
end

def update
  @product = Product.find(params[:id])
  if @product.update_attributes(product_params)
    redirect_to user_products_path, notice: "Pomyślnie zaktualizowano produkt"
  else
    render action: :edit
  end
end

def destroy
  @product = Product.find(params[:id])
  @product.destroy
  redirect_to user_products_path, notice: "Pomyślnie usunięto produkt"
end

private

def product_params
  params.require(:product).permit(
    :name,
    :category_id,
    :description,
    :long_description,
    :price,
    {photo: []},
    :condition
  )
end
end

Działał bez zarzutu ale chciałem dorzucić pare rzeczy takie jak podgląd, drag’n drop itp.
Korzystam z tego gem’a dropzonejs-rails

widok:

    <%= simple_form_for [:user, @product], html: {id: "dropzone-form-id"} do |f| %>
    <%= f.input :name, label: "Nazwa" %>
    <%= f.input :description, label: "Opis" %>
    <%= f.input :long_description, label: "Długi opis" %>
    <%= f.input :price, label: "Cena" %>
    <%= f.association :category, label: "Kategoria" %>
    <%= f.input :condition, label: "Stan", :collection => [['Nowy','Nowy'],['Używany','Używany']] %>

  <div id="files-field"
       class="dropzone"
       style="border: 2px dashed rgba(0, 0, 0, 0.3);
              min-height: 100px !important;">
    <div class="dz-message"
         style="margin: 20px">
      Drag your cats' pics here! Or
      <button>
        select files
      </button>
    </div>
  </div>

  <p>
    <%= f.submit %>
  </p>
<% end %>

upload-dropzone.js

    // .js file
Dropzone.options.filesField = {
  url: "/user/products",
  addRemoveLinks: true,
  autoProcessQueue: false,
  uploadMultiple: true,
  accept: function(file, done) {
    $("div#files-field").css({"height": "auto"});
    done();
  },
  init: function() {
    var myDropzone = this;

    var form = document.getElementById('dropzone-form-id');
    form.addEventListener('submit', function(event) {
      // stop the form's submit event
      if(myDropzone.getQueuedFiles().length > 0){
        event.preventDefault();
        event.stopPropagation();
        myDropzone.processQueue();
      }
    });

    myDropzone.on("sendingmultiple", function(file, xhr, formData) {
      formData.append("name", $('#product_name').val());
      formData.append("description", $('#product_description').val());
      formData.append("long_description", $('#product_long_description').val());
      formData.append("price", $('#product_price').val());
      formData.append("category", $('#product_category_id').val());
      formData.append("condition", $('#product_condition').val());
    });
  },
  successmultiple: function(data,response) {
    alert(response);
  }
};

bez dodania linijki skip_before_action :verify_authenticity_token w kontrolerze wyskakuje błąd

Can't verify CSRF token authenticity.
Completed 422 Unprocessable Entity in 1ms (ActiveRecord: 0.0ms)



ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken):

po dodaniu wyskakuje

Started POST "/user/products" for 127.0.0.1 at 2019-07-30 15:29:27 +0200
Processing by User::ProductsController#create as JSON
Parameters: {"name"=>"", "description"=>"", "long_description"=>"", "price"=>"", "category"=>"", 
"condition"=>"", "file"=>{"0"=>#<ActionDispatch::Http::UploadedFile:0x00007fbe12aa45d8 @tempfile=# 
<Tempfile:/tmp/RackMultipart20190730-32614-658ixz.png>, @original_filename="Zrzut ekranu z 2019-03- 
05 11-37-48.png", @content_type="image/png", @headers="Content-Disposition: form-data; 
name=\"file[0]\"; filename=\"Zrzut ekranu z 2019-03-05 11-37-48.png\"\r\nContent-Type: image/png\r\n">}}
User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC 
LIMIT ?  [["id", 2], ["LIMIT", 1]]
↳ /home/dondaro/.rvm/gems/ruby-2.5.3/gems/activerecord-5.2.2/lib/active_record/log_subscriber.rb:98
Completed 400 Bad Request in 2ms (ActiveRecord: 0.2ms)



ActionController::ParameterMissing (param is missing or the value is empty: product):

app/controllers/user/products_controller.rb:60:in `product_params'
app/controllers/user/products_controller.rb:27:in `create'

z tego co widzę to jest generowany parametr “file” zamiast “photo” jak mam go zmienić? czy może lepiej go nie zmieniać? co mam zrobić żeby to działało? i jak nie pomijać weryfikacji tokena?