[JAVA] Implementierung der Funktionsfunktion [Rails] gem ancestry category

Einführung

Ich heiße Kusano. Dieser Beitrag wird eine Ausgabe sein, nachdem ich überprüft habe, was ich an der Programmierschule gelernt habe. Der Text ist schlecht, weil er ein Memo für mich ist, aber ich hoffe, er wird Anfängern so viel wie möglich helfen. Wie der Titel schon sagt, handelt der Inhalt von der Implementierung der Kategoriefunktion der Furima-App durch Teamentwicklung an der Schule. Ich denke, es gibt viele unreife Punkte. Bitte weisen Sie auf Mängel hin. Ich werde es von Zeit zu Zeit verbessern.

Fertiges Produkt

Wenn die übergeordnete Kategorie ausgewählt ist, wird das Ereignis ausgelöst und die Felder für Kind, Enkel und Auswahl werden angezeigt.

** Kategorie-Registrierungsbildschirm bei der Auflistung von Produkten ** Image from Gyazo

** Bildschirm mit Informationen zu Kategorieninformationen für detaillierte Produktinformationen ** qiita_カテゴリー商品情報.png

Montagevorgang

** 1. Modell erstellen und Zuordnung in DB definieren **

--Installation der Edelstein-Abstammung --Erstellen eines Kategoriemodells --category Erstellung einer Migrationsdatei

** 2. Kategorieregistrierungsfunktion **

--Routing-Einstellungen für JSON in Kinder- und Enkelkategorien --Items Controller-Instanzvariablendefinition für übergeordnete Kategorie --items Controller-Methodendefinition für JSON von Kinder- und Enkelkategorien

** 3. Kategorieninformationen aufrufen **

Modellerstellung / Zuordnungsdefinition zur DB

Verwenden Sie das Juwel "Abstammung" von Ruby on Rails, um Kategoriefunktionen hinzuzufügen.

Gemfile 


gem 'ancestry'

Erstellen Sie ein Kategoriemodell mit dem Befehl Rails g Model Category im Terminal. Beschreibe has_ancestory.

app/models/category.rb 


class Category < ApplicationRecord
  has_ancestry
  has_many :items
end

Schreiben Sie Folgendes in die Migrationsdatei für Kategorien und führen Sie den Befehl Rails db: migrate im Terminal aus.

db/category.rb&nbsp;


class CreateCategories < ActiveRecord::Migration[5.2]
  def change
    create_table :categories do |t|
      t.string :name,     null: false
      t.string :ancestry
      t.timestamps
    end
    add_index :categories, :ancestry
  end
end

Beschreiben Sie alle Kategorien in der Google-Tabelle. Die A-Spalte ist id, die B-Spalte ist name (Kategoriename) und die C-Spalte ist Abstammung (numerischer Wert, der Eltern und Nachkommen unterscheidet). Ich habe alle Kategorien in eine CSV-Datei geschrieben, aber es gab 1368 Zeilen, daher fiel mir die Eingabe schwer. (Ich erinnere mich an die Büroarbeit, die ich in meinem vorherigen Job gemacht habe.) Übrigens gibt es eine Kategorie ohne Enkelkinder. Achten Sie also darauf, den Wert der Vorfahren nicht zu verschieben. Sie können die Daten speichern, indem Sie die Schritte Datei → Herunterladen → durch Kommas getrennte Werte (aktuelles CSV-Blatt) ausführen. Image from Gyazo Image from Gyazo Fügen Sie die heruntergeladene CSV-Datei direkt in die Datenbankdatei ein. Cursor_と_category_csv_—_freemarket_sample_75a-2.png

Schreiben Sie Folgendes in die Datei seeds.rb und führen Sie den Befehl Rails db: seed im Terminal aus, um die CSV-Datei zu lesen und automatisch einen DB-Datensatz zu generieren. Obwohl dies eine Erklärung zum Beschreibungsinhalt ist, geben Sie die Datei an, die Sie nach foreach lesen möchten. Die Beschreibung darunter lautet model name.create (Spaltenname => Spalte, die Sie laden möchten). Zeile [0] → Eine Spalte ist id Zeile [1] → Spalte B ist Name (Kategoriename) Zeile [2] → C-Spalte ist Abstammung (numerischer Wert, der Eltern und Nachkommen unterscheidet)

db/seeds.rb&nbsp;


require "csv"

CSV.foreach('db/category.csv') do |row|
  Category.create(:id => row[0], :name => row[1], :ancestry => row[2])
end 

Kategorieregistrierungsfunktion

Routing-Einstellungen für JSON in Kategorien für Kinder und Enkelkinder Die beiden besten in der Sammlung sind die Routings für den diesmal erstellten JSON. Wenn Sie die Standardeinstellungen {fomat: 'json'} schreiben, gilt dies nur für JSON.

config/routes.rb&nbsp;


  resources :items do
    resources :comments,  only: [:create, :destroy]
    resources :favorites, only: [:create, :destroy]
    collection do
      get 'get_category_children', defaults: { fomat: 'json'}
      get 'get_category_grandchildren', defaults: { fomat: 'json'}
      get 'search'
      get 'post_done'
      get 'delete_done'
      get 'detail_search'
      get 'update_done'
    end
  end

Definition der Instanzvariablen der übergeordneten Kategorie für den Elementcontroller Definieren Sie die folgende Beschreibung in der neuen Methode. (Im Verlauf der Implementierung wird es auch für andere Aktionen verwendet, sodass es später als privat neu definiert und mit before_action überarbeitet wird.)

app/controllers/items_controller.rb&nbsp;


@category_parent_array = Category.where(ancestry: nil)

Elemente Definition der Controller-Methode für JSON von Kinder- und Enkelkategorien Die Beschreibung in Klammern von params [] beschreibt: parent_id und: child_id, die von ajax in der später erläuterten JavaScript-Datei gesendet werden.

app/controllers/items_controller.rb&nbsp;


  def get_category_children
    @category_children = Category.find("#{params[:parent_id]}").children
  end

  def get_category_grandchildren
    @category_grandchildren = Category.find("#{params[:child_id]}").children
  end

Erstellen Sie eine json.jbuilder-Datei und beschreiben Sie die Konvertierung in JSON-Daten.

rb:app/views/items/get_category_children.json.jbuilder&nbsp;


json.array! @category_children do |child|
  json.id child.id
  json.name child.name
end

rb:app/views/items/get_category_grandchildren.json.jbuilder&nbsp;


json.array! @category_grandchildren do |grandchild|
  json.id grandchild.id
  json.name grandchild.name
end

Legen Sie das Verhalten bei der Auswahl eines Elternteils, Kindes oder Enkels mit JavaScript fest

app/assets/javascripts/category.js&nbsp;


$(function(){
  function appendOption(category){
    var html = `<option value="${category.id}">${category.name}</option>`;
    return html;
  }
  function appendChildrenBox(insertHTML){
    var childSelectHtml = "";
    childSelectHtml = `<div class="category__child" id="children_wrapper">
                        <select id="child__category" name="item[category_id]" class="serect_field">
                          <option value="">---</option>
                          ${insertHTML}
                        </select>
                      </div>`;
    $('.append__category').append(childSelectHtml);
  }
  function appendGrandchildrenBox(insertHTML){
    var grandchildSelectHtml = "";
    grandchildSelectHtml = `<div class="category__child" id="grandchildren_wrapper">
                              <select id="grandchild__category" name="item[category_id]" class="serect_field">
                                <option value="">---</option>
                                ${insertHTML}
                                </select>
                            </div>`;
    $('.append__category').append(grandchildSelectHtml);
  }

  $('#item_category_id').on('change',function(){
    var parentId = document.getElementById('item_category_id').value;
    if (parentId != ""){
      $.ajax({
        url: '/items/get_category_children/',
        type: 'GET',
        data: { parent_id: parentId },
        dataType: 'json'
      })
      .done(function(children){
        $('#children_wrapper').remove();
        $('#grandchildren_wrapper').remove();
        var insertHTML = '';
        children.forEach(function(child){
          insertHTML += appendOption(child);
        });
        appendChildrenBox(insertHTML);
      })
      .fail(function(){
        alert('Die Kategorie konnte nicht abgerufen werden');
      })
    }else{
      $('#children_wrapper').remove();
      $('#grandchildren_wrapper').remove();
    }
  });
  $('.append__category').on('change','#child__category',function(){
    var childId = document.getElementById('child__category').value;
    if(childId != "" && childId != 46 && childId != 74 && childId != 134 && childId != 142 && childId != 147 && childId != 150 && childId != 158){
      $.ajax({
        url: '/items/get_category_grandchildren',
        type: 'GET',
        data: { child_id: childId },
        dataType: 'json'
      })
      .done(function(grandchildren){
        $('#grandchildren_wrapper').remove();
        var insertHTML = '';
        grandchildren.forEach(function(grandchild){
          insertHTML += appendOption(grandchild);
        });
        appendGrandchildrenBox(insertHTML);
      })
      .fail(function(){
        alert('Die Kategorie konnte nicht abgerufen werden');
      })
    }else{
      $('#grandchildren_wrapper').remove();
    }
  })
});

Ich werde die obige Beschreibung erklären. Das Ereignis wird ausgelöst, wenn im übergeordneten Auswahlfeld eine Kategorie ausgewählt wird, die zuerst in der folgenden Beschreibung in der mittleren Zeile angezeigt wird. Die Beschreibung in der zweiten Zeile erhält die ID der ausgewählten Kategorie und definiert die Variablen.


$('#item_category_id').on('change',function(){
    var parentId = document.getElementById('item_category_id').value;

Fügen Sie als Nächstes die ID der von ajax in ① erfassten Kategorie in parent_id ein, übergeben Sie die parent_id über die zuvor geroutete Route für JSON an den Controller und erfassen Sie den Datensatz der untergeordneten Kategorie.


      $.ajax({
        url: '/items/get_category_children/',
        type: 'GET',
        data: { parent_id: parentId },
        dataType: 'json'
      })

Wenn die Ajax-Kommunikation erfolgreich ist, wird der Datensatz der in ② erfassten untergeordneten Kategorie in der 5. Zeile um die forEach-Methode erweitert. Die Entfernungsmethode in der 2. und 3. Zeile wurde geschrieben, um die Auswahlfelder für Kinder und Enkel zu entfernen, wenn im übergeordneten Auswahlfeld erneut eine andere Kategorie ausgewählt wird.


.done(function(children){
        $('#children_wrapper').remove();
        $('#grandchildren_wrapper').remove();
        var insertHTML = '';
        children.forEach(function(child){
          insertHTML += appendOption(child);
        });
        appendChildrenBox(insertHTML);
      })

Die in der oberen Zeile beschriebene appendOption übergibt den zuvor mit dem Argument appendOption (child) in der 6. Zeile von ③ erfassten untergeordneten Datensatz und bettet id und name (Kategoriename) in das Options-Tag ein.


  function appendOption(category){
    var html = `<option value="${category.id}">${category.name}</option>`;
    return html;
  }

Fügen Sie für appendChildrenBox den Inhalt von ④ in das in der 6. Zeile von ③ beschriebene insertHTML ein und übergeben Sie das Options-Tag von ④ in dem in der 8. Zeile von ③ beschriebenen Argument von appendChildrenBox (insertHTML). Betten Sie das Optionstag mit der Beschreibung von \ $ {insertHTML} ein. Schließlich die Beschreibung von $ ('.append__category'). Append (childSelectHtml); bewirkt, dass der Browser das untergeordnete Auswahlfeld asynchron anzeigt. Der Ablauf des Enkel-Auswahlfelds ist der gleiche.


  function appendChildrenBox(insertHTML){
    var childSelectHtml = "";
    childSelectHtml = `<div class="category__child" id="children_wrapper">
                        <select id="child__category" name="item[category_id]" class="serect_field">
                          <option value="">---</option>
                          ${insertHTML}
                        </select>
                      </div>`;
    $('.append__category').append(childSelectHtml);
  }

Wenn die Ajax-Kommunikation fehlschlägt, wird eine Warnung angezeigt.


      .fail(function(){
        alert('Die Kategorie konnte nicht abgerufen werden');
      })

Für die oben beschriebene if-Anweisung ajax wird der Anfangswert mit der Option include_blank von collection_select in der haml-Datei auf nil gesetzt. Wenn die Option mit der ID von nil ausgewählt wird, beginnt die Ajax-Kommunikation. Im Gegenteil, wenn es auf den Anfangswert von "Bitte auswählen" zurückgesetzt wird, wird es zu "else" und das Auswahlfeld für Enkel wird gelöscht.


 if (parentId != ""){
#Die Beschreibung in der Mitte wird weggelassen
    }else{
      $('#grandchildren_wrapper').remove();

In Bezug auf den Unterschied zwischen der Beschreibung des Kindes und der Beschreibung des Enkels muss die Beschreibung des Enkels wie folgt beschrieben werden, wenn die von JavaScript hinzugefügte Beschreibung für das Auslösen von Ereignissen vorgesehen ist. \ $ (Untersuchungsbereich) .on (Ereignisname, Ort, an dem das Ereignis auftritt, function () { Darüber hinaus wird die bedingte Verzweigung so festgelegt, dass die Ajax-Kommunikation beginnt, wenn die if-Anweisung nicht in der Kategorie ohne Enkelkinder enthalten ist.


$('.append__category').on('change','#child__category',function(){
    var childId = document.getElementById('child__category').value;
    if(childId != "" && childId != 46 && childId != 74 && childId != 134 && childId != 142 && childId != 147 && childId != 150 && childId != 158){

Es gibt eine Einschränkung, wenn das Auswahlfeld asynchron im Browser angezeigt wird. Hier geht es um den Teil, in dem "item [category_id]" im Auswahl-Tag für Kinder und Enkelkinder mit der Option name festgelegt ist. Die Option name gibt an, welche Kategorie-ID von Eltern, Kindern oder Enkeln in der Elementtabelle gespeichert werden soll.

** Namensoption nur für Kinder hinzufügen und Enkelkategorie eingeben ** → In der DB wird die untergeordnete ID gespeichert ** Namensoption nur für Enkelkinder hinzufügen, Kategorie ohne Enkelkinder eingeben ** → In der Datenbank wird die übergeordnete Kategorie-ID gespeichert ** Fügen Sie eine Namensoption für Kinder und Enkelkinder hinzu und geben Sie bis zur Kategorie Enkelkinder ein ** → In der Datenbank wird das Auswahl-Tag mit der am Ende asynchron angezeigten Namensoption mit Priorität gespeichert.

Der Grund, warum die Kategorie-ID des Enkels gespeichert werden muss, besteht darin, dass die übergeordneten und untergeordneten Datensätze beim Aufrufen der Kategoriedaten basierend auf der Kategorie-ID des Enkels aufgerufen werden können.


  function appendChildrenBox(insertHTML){
    var childSelectHtml = "";
    childSelectHtml = `<div class="category__child" id="children_wrapper">
                        <select id="child__category" name="item[category_id]" class="serect_field">
                          <option value="">---</option>
                          ${insertHTML}
                        </select>
                      </div>`;
    $('.append__category').append(childSelectHtml);
  }
  function appendGrandchildrenBox(insertHTML){
    var grandchildSelectHtml = "";
    grandchildSelectHtml = `<div class="category__child" id="grandchildren_wrapper">
                              <select id="grandchild__category" name="item[category_id]" class="serect_field">
                                <option value="">---</option>
                                ${insertHTML}
                                </select>
                            </div>`;
    $('.append__category').append(grandchildSelectHtml);
  }

Zeigen Sie das übergeordnete Auswahlfeld in der Haml-Datei an.

rb:app/views/items/_form.html.haml&nbsp;


    .append__category
      .category
        .form__label
          .lavel__name 
Kategorie
          .lavel__Required
            [Verpflichtend]
        =f.collection_select :category_id, @category_parent_array, :id, :name,{ include_blank: "Bitte auswählen"},class:"serect_field"

Kategorieninformationen aufrufen

Definieren Sie übergeordnete, untergeordnete und Enkelinstanzvariablen in der show-Methode des Elementcontrollers

app/controllers/items_controller.rb&nbsp;


@category_id = @item.category_id
@category_parent = Category.find(@category_id).parent.parent
@category_child = Category.find(@category_id).parent
@category_grandchild = Category.find(@category_id)

Rufen Sie die Kategorie, die mit der zuvor im Element-Controller definierten Instanzvariablen registriert wurde, in der Ansicht mit einer Haml-Datei auf. Die if-Anweisung ist abhängig von der Anzeige ohne Enkelkinder oder mit Enkelkindern. (Da der Pfad diesmal nicht für den Link angegeben ist, wird er als # festgelegt.)

rb:app/views/items/_main_show.html.haml&nbsp;


            %table 
              %tr 
                %th Verkäufer
                %td= @user.nickname
              %tr 
                %th Kategorie
                - if [46, 74, 134, 142, 147, 150, 158].include?(@category_id)
                  %td
                    = link_to "#{@category_child.name}","#"
                    %br= link_to "#{@category_grandchild.name}","#" 
                -else
                  %td
                    = link_to "#{@category_parent.name}","#"
                    %br= link_to "#{@category_child.name}","#"
                    = link_to "#{@category_grandchild.name}","#"
              %tr
                %th Marke
                %td= @item.brand_name
              %tr
                %th Produktgröße
                %td
              %tr
                %th Produktstatus
                %td= @item.item_status
              %tr
                %th Versandkosten
                %td= @item.delivery_fee
              %tr
                %Versandbereich
                %td= link_to "#{@item.shipping_origin}","#"
              %tr
                %Voraussichtliches Versanddatum
                %td= @item.days_until_shipping

Artikel, die ich als Referenz verwendet habe

Realisieren Sie das Auswahlfeld für dynamische Kategorien mithilfe mehrschichtiger Daten nach Herkunft ~ Ajax ~ [Übersetzung] Gem Ancestry Official Document

Recommended Posts

Implementierung der Funktionsfunktion [Rails] gem ancestry category
[Rails] Implementierung der Kategoriefunktion
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Vorbereitung"
[Schienen] Kategoriefunktion
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der "Seed Edition" der Vorfahren
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Edit Form Edition"
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Erstellungsformular"
Implementierung der Fuzzy-Suchfunktion für Schienen
Implementierung der Kategorie-Pulldown-Funktion
[Rails] Implementierung der Tutorial-Funktion
[Rails] Implementierung einer ähnlichen Funktion
[Rails] Implementierung der CSV-Importfunktion
[Rails] Implementierung der Bildvorschau
[Rails] Über die Implementierung der Like-Funktion
[Rails] Implementierung der Benutzerrückzugsfunktion
[Rails] Implementierung der CSV-Exportfunktion
[Rails] Implementierung von Viele-zu-Viele-Kategoriefunktionen
[Ruby on Rails] Implementierung der Kommentarfunktion
[Rails] Memo zur Implementierung der Kommentarfunktion
[Ruby on Rails] Folgen Sie der Funktionsimplementierung: Bidirektional
Rails [Für Anfänger] Implementierung der Kommentarfunktion
Rails Grundgerüst für die Implementierung der CRUD-Funktion
[Ruby on Rails] Implementierung einer ähnlichen Funktion
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Ich habe versucht, ein Fenster mit Bootstrap 3 zu erstellen"
Implementierung der DM-Funktion
Schienen folgen der Funktion
[Rails] Benachrichtigungsfunktion
Implementierung der Ruby on Rails-Anmeldefunktion (Sitzung)
[Rails] Implementierung der Bildvergrößerungsfunktion mit Lightbox2
Implementieren Sie die Produktkategoriefunktion mit Abstammung ① (Vorbereitung)
Ruby on Rails Implementierung der automatischen Mail-Sendefunktion
Implementierung der Rails-Hashtag-Suche
Implementierung des Rails6-Countdown-Timers
[Schienen] gem'payjp'implementierungsverfahren
Implementierung der Ruby on Rails-Anmeldefunktion (Devise Edition)
Implementierung der Rails CRUD-Funktion ② (diesmal bearbeitet und detailliert)
Implementierung der Kommentarfunktion (Ajax)
Implementierung von Rails Action Text
Implementierung der Ajax-Funktion (Follow Function)
Implementierung der Suchfunktion
[Für Anfänger von Rails] Mehrfachsuchfunktion ohne Gem implementiert
Implementierung der Bildvorschau-Funktion
Implementierung der Pagenationsfunktion
Suchfunktion [Implementierung kopieren und einfügen]