[RUBY] Implementierungsmethode zum Verknüpfen mehrerer Bilder mit einem Beitrag und zum gleichzeitigen Posten

Einführung

Ich habe einen Artikel als Memorandum veröffentlicht, in dem ich Schwierigkeiten hatte, die Funktion zum Posten mehrerer Bilder zu implementieren

Starten Sie die App

$ rails _5.2.3_neuer App-Name-d mysql
$Name der CD-App
$ bin/rails db:create

Einführung von Haml

Da diese Implementierung mit haml durchgeführt wird, werden wir haml einführen

Fügen Sie der Gem-Datei Folgendes hinzu Vergessen Sie nicht, die Bundle-Installation durchzuführen

gem 'haml-rails'

Erstellen Sie einfach eine Post-Funktion

routes


Rails.application.routes.draw do
  root 'products#index'
  resources :products, only: [:index, :new, :create]
end

controller


class ProductsController < ApplicationController
  def index
    @products = Product.includes(:images).order('created_at DESC')
  end

  def new
    @product = Product.new
    @product.images.new
  end

  def create
    @product = Product.new(product_params)
    if @product.save
      redirect_to root_path
    else
      render :new
    end
  end
  

  private

  def product_params
    params.require(:product).permit(:name, images_attributes: [:src])
  end

end

Modell und Migration

Produktmigrationsdatei

class CreateProducts < ActiveRecord::Migration[5.2]
  def change
    create_table :products do |t|
      t.string :name

      t.timestamps
    end
  end
end

Bildmigrationsdatei


 class CreateImages < ActiveRecord::Migration[5.2]
  def change
    create_table :images do |t|
      t.string :src
      t.references :product, foreign_key: true

      t.timestamps
    end
  end
end

Produktmodell


class Product < ApplicationRecord
  has_many :images
  accepts_nested_attributes_for :images, allow_destroy: true
end

Bildmodell


class Image < ApplicationRecord
  mount_uploader :src, ImageUploader
  belongs_to :product
end

Wir können Bilder mit dem Bildmodell hochladen.

Fügen Sie der Installation von Gemfile und $ bundle Folgendes hinzu

gem 'carrierwave'
gem 'mini_magick'

Erstellen Sie einen Uploader

Gehen Sie im Terminal wie folgt vor

$ rails g uploader image

Als Nächstes wurde die Datei image_uploader.rb generiert. Bearbeiten Sie daher Folgendes

include CarrierWave::MiniMagick  //Finden Sie diese Beschreibung und Kommentar

process resize_to_fit: [100, 100]  //Diese Beschreibung wurde hinzugefügt

Zum Schluss bearbeiten Sie haml und scss

haml/new



.lead
  =link_to "/products" do
    =image_tag "http://furima.tokyo/assets/logo-d3d78326971d78b06e3d6f0ba666d025a8ad681286b4d9e00e7dbe8673bcfd23.svg", class: "lead__img"
  
= form_with model: @product, local: true do |f|
  .input-field
    .input-field__contents
      .input-field__contents-image
        .input-field__contents-image__headline
          .headlabel
Ausstellungsbild
            %span.necessary
Verpflichtend
        %p.upload
Sie können bis zu 5 Fotos hochladen
        
        #image-box-1 
          .item-num-0#image-box__container
            = f.fields_for :images do |i|
              .input-field__contents-image__drop__js-file
                .input-area
                  = i.file_field :src
    
      .input-field__contents-name
        .input-field__contents-image__headline
          .headlabel
            %label
Produktname
              %span.necessary
Verpflichtend
          .name-input
            = f.text_field :name, {class: "drop-input", placeholder: "Bis zu 40 Zeichen"}
    
    .input-field
      .input-field__contents
        .input-field__contents-price
          .sell
            = f.submit "Verkaufen", class: "sellbtn", tabindex: "0"

new.scss



.lead {
  background-color: rgb(245, 245, 245);
  text-align: center;
  height: 128px;
  line-height: 10;
}
.input-field {
  background-color: rgb(245, 245, 245);
  width: 100%;
  .input-field__contents {
    left: 0;
    background-color: white;
    max-width: 800px;
    margin: 0 auto;
    padding: 40px;
    border-bottom: 1px solid hsl(0, 0%, 77%);
    height: 100%;
    .input-field__contents-image {
      width: 800px;
      border-bottom: rgb(204, 204, 204);
      .input-field__contents-image__headline{
        margin-top: 20px;
        margin-left: 5px;
      }
      .upload {
        margin-top: 16px;
        margin-left: 5px;
      }
      #image-box-1 {
        display: flex;
        height: 130px;
        width: 100%;
        margin-right: 0px;
        text-align: center;
        i{
          padding-top: 50px;     
        }
        .item-num-0#image-box__container  {
        background-color: rgb(245, 245, 245);
        height: 100%;
        width: 100%;
        border-width: 1px;
        border-style: dashed;
        border-color: rgb(204, 204, 204);
        border-image: initial;
        text-align: center;
        }
      }
    }
  }
  .drop-input {
    width: 60%;
    height: 50px;
    border-color: #cccccc;
    border-radius: 4px;
    border-style: solid;
    border-width: 1px;
    margin: 10px 10px 0 0;
  }  
  .name-input{
    .drop-input{
      width: 100%;
      height: 50px;
      border-color: #cccccc;
      border-style: solid;
    }
  } 
  .sell {
    text-align: center;
    display: grid;
    width: 50%;
    margin-left: 200px;
    .sellbtn {
      background-color: #3ccace;
      color: white;
      border-color: transparent;
      font-weight: 600;
      line-height: 3;
      cursor: pointer;
    }
  }
}

Wenn es wie folgt aussieht, ist es vollständig. https://gyazo.com/a1d705516656f50c689abc7c18de5ec9

Poste mehrere Bilder

Einführung von jQuery

gem 'jquery-rails'

Führen Sie dann die Bundle-Installation durch

Bearbeiten von application.js

//= require rails-ujs
//= require activestorage
//= require jquery
//= require_tree .

New.haml bearbeiten


-#Vor dem Bearbeiten
#image-box-1 
 .item-num-0#image-box__container
  = f.fields_for :images do |i|
   .input-field__contents-image__drop__js-file
    .input-area
     = i.file_field :src
-#Nach der Bearbeitung

#image-box-1 
 .item-num-0#image-box__container
  = f.fields_for :images do |i|
   .input-field__contents-image__drop__js-file
    .input-area
    = i.file_field :src, type: 'file', name: "product[images_attributes][][name]", value:"", style: "display:none", id:"img-file"
    %label{for: "img-file"}
     %i.fas.fa-camera

Erstellen und bearbeiten Sie new.js, um mehrere Bilder zu veröffentlichen

new.js


$(function(){
  //Erstellen Sie eine Box zum Speichern von Daten mit einem DataTransfer-Objekt
  var dataBox = new DataTransfer(); //Schritt ②
  //Datei mit querySelector_Feld bekommen
  var file_field = document.querySelector('input[type=file]')
  //Ereignis, das ausgelöst wird, wenn Datei ausgewählt wird
  $('#img-file').change(function(){
    //Holen Sie sich das Objekt der ausgewählten Datei mit prop
    var files = $('input[type=file]').prop('files')[0];
    $.each(this.files, function(i,file){
    //Lesen Sie das von readAsDataURL von FileReader angegebene File-Objekt
    var fileReader = new FileReader();

    //Datei zum DataTransfer-Objekt hinzufügen
    dataBox.items.add(file) //Schritt ②
    //Dateiliste der Dateien im dataTransfer-Objekt_Ersatz im Feld
    file_field.files =  dataBox.files //Schritt ②

    var num = $('.item-image').length + 1 + i //Schritt ②
    fileReader.readAsDataURL(file); //Schritt ②
     //Wenn die Anzahl der Bilder 10 erreicht, löschen Sie das Dropbox-Feld, wenn es überschritten wird
     if (num == 5){ //Schritt ②
      $('#image-box__container').css('display', 'none')
     }
    //Speichern Sie nach Abschluss des Ladevorgangs die URL der Datei in src
    fileReader.onloadend = function() {
      var src = fileReader.result
      var html = `<div class='item-image' data-image="${file.name}">
                    <div class=' item-image__content'>
                      <div class='item-image__content--icon'>
                        <img src=${src} width="150" height="90" >
                      </div>
                    </div>
                    <div class='item-image__operetion'>
                      <div class='item-image__operetion--delete'>Löschen</div>
                    </div>
                  </div>`
     //image_box__Fügen Sie HTML vor dem Containerelement ein
      $('#image-box__container').before(html);
      };
    //   fileReader.readAsDataURL(file);
    //  });
     //image-box__Ändern Sie die Containerklasse und die Größe der Dropbox mit CSS.
     $('#image-box__container').attr('class', `item-num-${num}`)
    });
  });
    $(document).on("click", '.item-image__operetion--delete', function(){
      //Vorschau-Element abrufen
      var target_image = $(this).parent().parent()
      //Vorschau löschen
      target_image.remove();
      //Löschen Sie die Datei im Eingabe-Tag
      file_field.val("")
    })
});

Scss bearbeiten


.lead {
  background-color: rgb(245, 245, 245);
  text-align: center;
  height: 128px;
  line-height: 10;
}

.input-field {
  background-color: rgb(245, 245, 245);
  width: 100%;
  &__contents {
    left: 0;
    background-color: white;
    max-width: 800px;
    margin: 0 auto;
    padding: 40px;
    border-bottom: 1px solid hsl(0, 0%, 77%);
    height: 100%;
  }
  
  .input-field__contents-image {
    width: 800px;
    border-bottom: rgb(204, 204, 204);
    .input-field__contents-image__headline{
      font-weight: 600;
      margin-top: 20px;
      margin-left: 5px;
      .name-input {
        height: 54px;
        .option-input {
          display: block;
          width: 93%;
          border-color: #cccccc;
          height: 100%;
          border-radius: 4px;
          font-weight: bolder;
          padding: 0px 2px 1px;
          border-width: 1px;
        }
      }
    }
    .upload {
      margin-top: 16px;
      margin-left: 5px;
    }
    #image-box-1 {
      display: flex;
      height: 130px;
      width: 100%;
      margin-right: 0px;
      text-align: center;
      i{
        padding-top: 50px;
        cursor: pointer;
      }
      .item-num-0#image-box__container  {
      background-color: rgb(245, 245, 245);
      height: 100%;
      width: 100%;
      border-width: 1px;
      border-style: dashed;
      border-color: rgb(204, 204, 204);
      border-image: initial;
      text-align: center;
      }
      .item-num-1{
        background-color: rgb(245, 245, 245);
      height: 100%;
      width: 100%;
      border-width: 1px;
      border-style: dashed;
      border-color: rgb(204, 204, 204);
      border-image: initial;
      text-align: center;
      }
      .item-num-2{
        background-color: rgb(245, 245, 245);
        height: 100%;
        width: 100%;
        border-width: 1px;
        border-style: dashed;
        border-color: rgb(204, 204, 204);
        border-image: initial;
        text-align: center;
      }
      .item-num-3{
        background-color: rgb(245, 245, 245);
        height: 100%;
        width: 100%;
        border-width: 1px;
        border-style: dashed;
        border-color: rgb(204, 204, 204);
        border-image: initial;
        text-align: center;
      }
      .item-num-4{
        background-color: rgb(245, 245, 245);
      height: 100%;
      width: 100%;
      border-width: 1px;
      border-style: dashed;
      border-color: rgb(204, 204, 204);
      border-image: initial;
      text-align: center;

      }
      .item-num-5{
        background-color: rgb(245, 245, 245);
        height: 100%;
        width: 100%;
        border-width: 1px;
        border-style: dashed;
        border-color: rgb(204, 204, 204);
        border-image: initial;
        text-align: center;
      }  
    }
    //Überprüfen Sie das Anzeige-CSS
    .item-image{
      height: 130px;
      width: 160px;
      border: 1px solid #eee;
      margin-right: 10px;
      .item-image__content{
        padding-top: 10px;
        .item-image__content--icon{
        }
      }
      .item-image__operetion{
        .item-image__operetion--delete{
          color: #00b0ff;
          cursor: pointer;
          padding-top: 5px;
         text-align: center;

        }
      }
    }
  }

  .text-area {
    border-radius: 4px;
    font-size: 16px;
    padding: 13px 16px;
    border-color: #cccccc;
    margin-top: 30px;
    
  }
  .drop-input {
    width: 100%;
    height: 50px;
    border-color: #cccccc;
    border-radius: 4px;
    border-style: solid;
    border-width: 1px;
    margin: 10px 10px 0 0;
    ::placeholder {
      padding: 20px;
      font-weight: inherit;
    } 
  }
 
  .headlabel {
    margin-top: 30px;
    .necessary {
      background-color: #3ccace;
      color: white;
      padding: 2px 4px;
      font-size: 14px;
      margin-left: 3px;
      cursor: pointer;
      border-radius: 2px;
     }
  }
  .sell {
    text-align: center;
    display: grid;
    width: 50%;
    margin-left: 200px;
    .sellbtn {
      background-color: #3ccace;
      color: white;
      font-size: 20px;
      min-height: 48px;
      padding: 0 24px;
      border-color: transparent;
      border-radius: 2px;
      font-weight: 600;
      line-height: 3;
    }
  }
}

Damit ist der gesamte Vorgang abgeschlossen Überprüfen Sie den Betrieb https://gyazo.com/372657130a2696e1865c02fdd6e9e303

Bearbeitungs- und Löschfunktionen werden in einem separaten Artikel fortgesetzt

Recommended Posts

Implementierungsmethode zum Verknüpfen mehrerer Bilder mit einem Beitrag und zum gleichzeitigen Posten
[Java] Fehler beim Methodenaufruf, wenn Vererbung und Schnittstellenimplementierung gleichzeitig ausgeführt werden
[Spring Boot] Poste Dateien und andere Daten gleichzeitig [Axios]
[Mehrere Fotos registrieren] Registrieren Sie mehrere Schienenbilder gleichzeitig. Primitive Power-Technik
[Spring Boot] POST-Datei-Array / Liste und andere Daten gleichzeitig [Axios]
Methode, um die Anzahl der Jahre zu addieren und das Monatsende zu erhalten
So rufen Sie mehrere Namen gleichzeitig in derselben Kategorie auf
Zeichnen Sie mit MPAndroidChart gleichzeitig Balkendiagramm und Liniendiagramm
So ändern Sie die maximale und maximale Anzahl von POST-Daten in Spark
Ich möchte das Argument der Annotation und das Argument der aufrufenden Methode an den Aspekt übergeben
Wählen Sie die erste nicht leere aus mehreren Optional aus und rufen Sie ihre Methode auf
Ich habe versucht, die Grammatik von R und Java zu übersetzen [Von Zeit zu Zeit aktualisiert]
So implementieren Sie die E-Mail-Authentifizierungsfunktion zum Zeitpunkt der Benutzerregistrierung
[Rails] So lösen Sie die Zeitverzögerung von created_at nach der Speichermethode
[Java] Ist es nicht erforderlich, "Identität" bei der Implementierung der equals () -Methode zu überprüfen?
[Ruby] Definieren Sie die Hierarchie gleichzeitig mit der Initialisierung von Hash mit der Tap-Methode
Stellen Sie die Zeit von LocalDateTime auf eine bestimmte Zeit ein
Ausgabe der Verwendung der Slice-Methode
Zusammenfassung der japanischen Zeiteinstellung und Anzeigemethode
So löschen Sie den dem Benutzer zugeordneten Tweet, wenn Sie ihn gleichzeitig löschen
Offline-Echtzeit zum Schreiben eines F04-Ruby- und C99-Implementierungsbeispiels
Verhalten beim gleichzeitigen Hinzufügen von RadioButton und Erstprüfung im Code festgestellt