CSVファイルをインポートしてデータベース/テーブルに登録って段取りは結構メジャーで、既に幾つも解説記事が上がってる。その節はお世話になりました。
前はその通りにやって出来たのだけど、今新しいプロジェクトでソースを使い回すと何故か出来ない。確実ではないけど、ひょっとしたらrailsかrubyのバージョンによって出来ないとかあんのか?となったので、今できてるものを以下にメモ的に置いておきます。少なくとも自分はこれで半日潰しました。
バージョンはruby 3.04、rails 6.1.7です。ちゃんとした仕組みとか解説は他を読んだ方がいいよ。
Gemfile
とりあえず
gem 'roo'
bundle installとかもしておくように。
application.rb
一応csvのrequireを書いておく
reuire "rails/all"
require 'csv'
views
ここが以前と特に違う。
以前は参考にしたサイトはどこも、パスの指定がimport_hoge_pathのように、アクション名_コントローラー名_pathという表記されていた。実際に以前はこの表記で通っていたけど、現状ではなぜか通らないので通常のコントローラー名_アクション名_pathの記法とする。理由は何かあるんだろうけどわからない。
一応いうと、hoge_controllerと紐付いてる前提です。
<%= form_with url: hoge_import_path do |form| %>
<%= form.file_field :file, accept: '.csv' %>
<%= form.submit "インポート" %>
<% end %>
Routes
ここも参考サイトはどこもかしこも判で押したようにresourcesで指定していたが、とくにresourcesでなきゃいけない理由もないと思うので普通に指定
post 'hoge/import' => 'hoge#import'
controller
Userモデルにデータをぶちこむというサンプル。ここからは先行の参考サイトと全く同じ。
def import
User.import(params[:file])
redirect_to root_url
end
model
モデルのところまで持ち込まれたファイルをデータにぶちこんでいく作業。
ここでは名前が既存データになければ登録していくという仮定になっている。
class User < ApplicationRecord
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
#nameが見つからなければ新しく作成
user = find_by(name: row["name"]) || new
user.attributes = row.to_hash.slice(*updatable_attributes)
user.save
end
end
def self.updatable_attributes
["name","address","age","phone"]
end
end
ほとんどコピーみたいなもんなんで、すみません。
エンコード直すのとかも入れてもいいかもだけど、まぁとりあえず。