[RUBY] [Rails6 + Vue.js] Implementieren Sie den CSV-Importprozess mithilfe von Axios

Notieren Sie sich die Notwendigkeit, mehrere CSV-Dateien mithilfe von Vue.js und der Rails-API in ihre jeweiligen Tabellen zu importieren.

bitte beachten Sie

Es wurde von einem Anfänger geschrieben, der Rails, Vue.js, als Memorandum lernt. Es besteht die Möglichkeit, dass der Inhalt Fehler enthält, und es besteht die Möglichkeit, dass es eine bessere Methode gibt. Denken Sie also bitte daran, wenn Sie darauf verweisen. Wenn Sie Fragen haben, können Sie diese gerne kommentieren.

Was Sie erreichen wollen

Ich möchte ein Eingabefeld vorbereiten und Axios verwenden, um in die Tabelle zu POSTEN, in der die ausgewählten CSV-Dateien (2 Typen) jeweils vorbereitet sind.

Tabelle csv1 ⇨ code_lists csv2 ⇨ Finanztabelle Die Tabellendefinition lautet wie folgt.

code_listet Tabelle auf


  create_table "code_lists", force: :cascade do |t|
    t.string "edinet"
    t.string "securities"
    t.string "company"
    t.string "sector"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["company"], name: "index_code_lists_on_company"
    t.index ["edinet"], name: "index_code_lists_on_edinet", unique: true
    t.index ["securities"], name: "index_code_lists_on_securities"
  end

Finanztabelle


  create_table "financials", force: :cascade do |t|
    t.string "edinet"
    t.date "rec_date"
    t.string "account_name"
    t.float "value"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["account_name"], name: "index_financials_on_account_name"
    t.index ["edinet", "rec_date", "account_name"], name: "index_financials_on_edinet_and_rec_date_and_account_name", unique: true
    t.index ["edinet"], name: "index_financials_on_edinet"
  end

Vorbereitung

Fügen Sie die Bibliothek im Voraus hinzu.

config/application.rb


require 'csv' #Nachtrag

Fügen Sie Gem Roo und "Bundle Install" hinzu

Gemfile


gem 'roo'

Da zum Zeitpunkt von "axios-post" "csrf" -Token-Gegenmaßnahmen erforderlich sind, setzen Sie ein separates Plug-In. Erstellen Sie einen neuen Plugins-Ordner.

app/javascript/packs/plugins/vue-axios.js


const VueAxiosPlugin = {}
export default VueAxiosPlugin.install = function(Vue, { axios }) {
  const csrf_token = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
  axios.defaults.headers.common = {
    "X-Requested-With": "XMLHttpRequest",
    "X-CSRF-Token": csrf_token
  }

  Vue.axios = axios
  Object.defineProperties(Vue.prototype, {
    axios: {
      get () {
        return axios
      }
    }
  })
}

Importieren Sie das Plug-In in die Eingabedatei

hello_vue.js


import Vue from "vue/dist/vue.esm";
import axios from "axios"; //hinzufügen
import VueAxiosPlugin from "./plugins/vue-axios";  //hinzufügen
import App from "./components/App.vue";

Vue.use(VueAxiosPlugin, { axios: axios }) //hinzufügen

new Vue({
  el: "#app",
  render: h => h(App),
})

Routing

Ich stelle das Routing wie folgt ein: Es werden nur die erforderlichen Teile aufgelistet. Jedes hat Rails API-Routing-Einstellungen. CSV-Datei für die Tabelle code_lists in api / code_lists / import POSTEN Sie die CSV-Datei für die Finanztabelle an api / Financials / Import.

config/routes.rb


Rails.application.routes.draw do
  (Oben weggelassen)
  namespace :api, format: 'json' do
    resources :code_lists do
      post :import, on: :collection
    end
  end

  namespace :api, format: 'json' do
    resources :financials do
      post :import, on: :collection
    end
  end
  (Unten weggelassen)
end

View Die Ansicht sieht folgendermaßen aus:

Import.vue


<template>
  <div>
    <div class="import-form">
      <input @change="selectedFile" type="file" name="file">
    </div>
    <div class="import-form">
      <button @click="upload('/api/code_lists/import')" type="submit">Codeliste hochladen</button>
    </div>
    <div class="import-form">
      <button @click="upload('/api/financials/import')" type="submit">Finanzdaten hochladen</button>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  data: function(){
    return {
      uploadFile: null
    };
  },
  methods: {
    selectedFile: function(e) {
      //Speichern Sie die Informationen der ausgewählten Datei
      e.preventDefault();
      let files = e.target.files;
      this.uploadFile = files[0];
    },
    upload: function(url) {
      //POST-Datei mit FormData
      let formData = new FormData();
      formData.append('file', this.uploadFile);
      // let config = {
      //     headers: {
      //         'content-type': 'multipart/form-data'
      //     }
      // };
      axios
          .post(url, formData)
          .then(function(response) {
              //Antwortverarbeitung
          })
          .catch(function(error) {
              //Fehlerbehandlung
          })
    }
  }
}
</script>

Speichern Sie die Datei nach Auswahl der Datei im Eingabefeld mit der Methode selectedFile in uploadFile. Anschließend wird die Upload-Methode im Klickereignis der Schaltfläche ausgeführt. POSTEN Sie die Datei an die URL des Upload-Methodenarguments (die beiden URLs, die Sie zuvor in Routen festgelegt haben). Der Punkt ist, dass die im Voraus gespeicherte uploadFile beim POSTing an das FormData-Objekt übergeben wird. Ich habe auskommentiert, weil ich diesmal config nicht verwendet habe.

Controller und Modell

Dieses Mal wird es eine Implementierung sein, die zwei CSV-Dateien in jede Tabelle importiert, und es ist notwendig, sie für jedes Modell zu implementieren. Da der Inhalt jedoch nahezu identisch ist, wird nur die Implementierung des Finanzmodells beschrieben. Zuerst über die Steuerung.

app/controllers/api/financials_controller.rb


class Api::FinancialsController < ApplicationController
  def import
    Financial.import(params[:file])
  end
end

Der Controller ruft nur die Class-Methode der Financial Class auf.

Als nächstes lautet die Beschreibung des Finanzmodells wie folgt.

app/models/financial.rb


class Financial < ApplicationRecord
  validates :edinet, presence: true
  validates :rec_date, presence: true
  validates :account_name, presence: true
  validates :value, presence: true
  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      #Wenn die ID gefunden wird, rufen Sie den Datensatz auf. Wenn er nicht gefunden wird, erstellen Sie einen neuen
      financial = find_by(edinet: row["edinet"], rec_date: row["rec_date"], account_name: row["account_name"]) || new
      #Holen Sie sich Daten von CSV und setzen Sie
      financial.attributes = row.to_hash.slice(*updatable_attributes)
      #sparen
      financial.save
    end
  end
  def self.updatable_attributes
    ["edinet", "rec_date", "account_name", "value"]
  end
end

Geben Sie den Spaltennamen der CSV, die Sie importieren möchten, in updatable_attributes ein. Außerdem wird find_by verwendet, um zu überprüfen, ob der Datensatz bereits importiert wurde. Wenn er bereits importiert wurde, wird er überschrieben.

Schließlich

Wenn Sie Fragen haben, können Sie diese gerne kommentieren. Wir entwickeln eine Anwendung, die die Finanzdaten börsennotierter Unternehmen verwendet. Wir entwickeln das Frontend mit Vue.js und das Backend mit der Rails-API. Ich möchte die Ergebnisse, die ich in einem Artikel gewonnen habe, weiter zusammenfassen. Vielen Dank, dass Sie bisher bei uns geblieben sind!

Artikel, auf die ich mich bezog: csrf-Maßnahmen: [Vue] -Axios können standardmäßig CSRF-Token festlegen Front-End-Implementierung: Wenn Sie eine Datei mit Vue.js veröffentlichen möchten Backend-Implementierung: [Ruby on Rails] CSV-Import

Recommended Posts

[Rails6 + Vue.js] Implementieren Sie den CSV-Importprozess mithilfe von Axios
[Rails] Implementierung der CSV-Importfunktion
Implementieren Sie die CSV-Download-Funktion in Rails
So implementieren Sie die Image-Veröffentlichung mithilfe von Schienen
Implementieren Sie Schaltflächenübergänge mit link_to in Rails
Implementieren Sie eine Freigabeschaltfläche in Rails 6, ohne Gem zu verwenden
Implementieren Sie die Sternebewertungsfunktion mit Raty in Rails 6
[Nuxt / Rails] POST-Implementierung mit axios und devise_token_auth
Schienen CSV Basic
Implementieren Sie die Rails-Paginierung