Nous avons décidé d'implémenter la fonction de téléchargement CSV dans Rails. Il y a déjà beaucoup d'exemples simples et excellents sur Qiita, et j'aurais pu l'implémenter facilement en regardant les articles ici.
La fonction de sortie CSV que j'ai trouvée au travail était beaucoup plus compliquée que celles-ci, j'ai donc décidé de l'implémenter tout en examinant ce que je pensais "Quel est ce mécanisme!" .. En gros, c'est proche du deuxième article présenté ci-dessus.
La version Rails est «5.2.4.2».
controller
Le contrôleur est presque le même que l'article présenté ci-dessus. Le format est divisé en html et csv, et lorsqu'il y a une demande au format csv, la méthode qui crée csv est appelée.
controllers/somethings_controller.rb
class SomethingsController < ApplicationController
include SomeCsvModule #Je vais le définir
def index
@somethings = Something.all
respond_to do |format|
format.html
format.csv do
generate_csv(@somethings) #Je vais le définir
end
end
end
end
view
La vue est très simple, il suffit d'installer un bouton avec format :: csv
^^.
ruby:views/somethings/index.html.haml
= link_to "Téléchargement CSV", somethings_path(format: :csv)
module
Le secret de cette vue et de ce contrôleur simples était dans le module. Puisqu'il s'agit d'une méthode courante pour divers contrôleurs, nous avons défini un module commun dans controllers / concerts /
.
/controllers/concerns/some_csv_module.rb
module SomeCsvModule
extend ActiveSupport::Concern
def generate_csv(somethings)
filename = "Liste d'informations_#{Date.today}.csv"
set_csv_request_headers(filename)
bom = "\uFEFF" #Je vais expliquer(1)
self.response_body = Enumerator.new do |csv_data| #Je vais expliquer(2,3)
csv_data << bom
header = %i(contenu du nom d'identifiant)
csv_data << header.to_csv #Je vais expliquer(4)
somethings.each do |some|
body = [
some.id,
some.name,
some.content
]
csv_data << body.to_csv
end
end
end
def set_csv_request_headers(filename, charset: 'UTF-8') #Je vais expliquer(5)
#↓ je vais expliquer(6)
self.response.headers['Content-Type'] ||= "text/csv; charset=#{charset}"
self.response.headers['Content-Disposition'] = "attachment;filename=#{ERB::Util.url_encode(filename)}"
self.response.headers['Content-Transfer-Encoding'] = 'binary'
end
end
BOM est une abréviation de «Byte Order Mark», qui est une courte chaîne de caractères au début d'un document écrit en «Unicode». Cette chaîne de caractères décrit la méthode de codage du document.
Le code de caractère standard d'Excel est Shift-JIS
, et le monde de WEB est ʻUTF-8`, donc si vous essayez d'ouvrir les données de sortie CSV avec l'application WEB dans Excel, les caractères seront définitivement déformés.
Vous pouvez éviter les caractères déformés en disant à bom
au début du document que le code de caractère de ce document est ʻUTF-8`.
Dans ce module, nous définissons bom =" \ uFEFF "
et ajoutons bom
au début des données au début du processus de création de données csv suivant.
De plus, l'explication de cette partie est créée en se référant à ces deux articles.
J'ai vérifié la partie self.response_body
, mais je ne l'ai pas bien comprise ... Pardon. Cependant, si vous devinez d'après les articles ici ...
La partie qui définit la vue que Rails rend semble être self.response_body
. La valeur par défaut est «nil» et vous pouvez créer une vue à rendre en affectant une valeur à «self.response_body».
ʻEnumerator.new` semble être une méthode ** "créer un élément de tableau" ** dans la mesure où j'ai vérifié en se référant à l'article suivant.
▼ Référence
Cette partie du code ci-dessus
self.response_body = Enumerator.new do |csv_data|
csv_data << bom
header = %i(contenu du nom d'identifiant)
csv_data << header.to_csv
somethings.each do |some|
body = [
#Omission
]
csv_data << body.to_csv
end
end
C'était la même chose.
csv_data = []
csv_data << bom
header = %i(contenu du nom d'identifiant)
csv_data << header.to_csv
somethings.each do |some|
body = [
#Omission
]
csv_data << body.to_csv
end
self.response_body = csv_data
to_csv
est une méthode de la bibliothèque csv et semble être une méthode qui convertit un tableau au format csv. Vous trouverez ci-dessous le code extrait de ce document.
require 'csv'
csv_string = ["CSV", "data"].to_csv # => "CSV,data"
csv_array = "CSV,String".parse_csv # => ["CSV", "String"]
La partie charset: 'UTF-8'
de cette méthode est appelée ** argument mot-clé **, qui est un moyen de spécifier une clé comme argument comme un hachage.
python
def set_csv_request_headers(filename, charset: 'UTF-8')
▼ Cliquez ici pour plus de détails
En le spécifiant comme ceci, vous pouvez appeler la valeur ʻUTF-8avec le mot-clé
charset` dans la méthode.
Enfin, voici la partie
python
self.response.headers['Content-Type'] ||= "text/csv; charset=#{charset}"
self.response.headers['Content-Disposition'] = "attachment;filename=#{ERB::Util.url_encode(filename)}"
self.response.headers['Content-Transfer-Encoding'] = 'binary'
Spécifie un ensemble d'options à ajouter à l'en-tête de réponse lorsque la réponse est renvoyée. Cliquez ici pour une liste d'options.
Pour expliquer brièvement chacun,
Content-Type
** ... Spécifiez le type MIME du contenu.Content-Disposition
** ... Spécifiez si le contenu est HTML (ʻinline) ou attaché (ʻattachment
). Avec l'option filename =" file name "
, vous pouvez ouvrir une fenêtre pour enregistrer sous (*)Content-Transfer-Encoding
** ... décrit comment la chaîne de requête est encodée (voir ici pour plus de détails (https: //wa3.i-). 3-i.info/word11117.html)))... il semble. La partie (*) est écrite dans le Document officiel, mais pour l'instant je suis N'a pas réussi dans cet environnement. Pardon. .. ..
... c'est ça! Il a fallu beaucoup d'apprentissage pour comprendre le mécanisme, mais j'ai réussi à implémenter la fonction de sortie CSV ^^
▼ Bouton de sortie CSV créé: ensoleillé:
Le code que j'ai vu au travail contenait encore diverses options dans l'en-tête de réponse, organisait les processus qui peuvent être partagés sous une forme généralisée et était plein de savoir-faire, mais tout d'abord, cela J'apprendrai la forme et maîtriserai diverses options.
(Tout d'abord, je veux pouvoir écrire un test pour cela ...) Je vais continuer à me consacrer ♪
Recommended Posts