1
1

More than 1 year has passed since last update.

RailsでCSVファイルをインポートする方法改

Posted at

CSVファイルをインポートしてデータベース/テーブルに登録って段取りは結構メジャーで、既に幾つも解説記事が上がってる。その節はお世話になりました。

前はその通りにやって出来たのだけど、今新しいプロジェクトでソースを使い回すと何故か出来ない。確実ではないけど、ひょっとしたらrailsかrubyのバージョンによって出来ないとかあんのか?となったので、今できてるものを以下にメモ的に置いておきます。少なくとも自分はこれで半日潰しました。

バージョンはruby 3.04、rails 6.1.7です。ちゃんとした仕組みとか解説は他を読んだ方がいいよ。

Gemfile

とりあえず

    gem 'roo'

bundle installとかもしておくように。

application.rb

一応csvのrequireを書いておく

config/application.rb
reuire "rails/all"
require 'csv'

views

ここが以前と特に違う。
以前は参考にしたサイトはどこも、パスの指定がimport_hoge_pathのように、アクション名_コントローラー名_pathという表記されていた。実際に以前はこの表記で通っていたけど、現状ではなぜか通らないので通常のコントローラー名_アクション名_pathの記法とする。理由は何かあるんだろうけどわからない。

一応いうと、hoge_controllerと紐付いてる前提です。

hoge/test.html.erb
  <%= form_with url: hoge_import_path do |form| %>
    <%= form.file_field :file, accept: '.csv' %>
    <%= form.submit "インポート" %>
  <% end %>

Routes

ここも参考サイトはどこもかしこも判で押したようにresourcesで指定していたが、とくにresourcesでなきゃいけない理由もないと思うので普通に指定

config/routes.rb
post 'hoge/import' => 'hoge#import'

controller

Userモデルにデータをぶちこむというサンプル。ここからは先行の参考サイトと全く同じ。

app/controllers/hoge_controller.rb

def import
    User.import(params[:file])
    redirect_to root_url
end

model

モデルのところまで持ち込まれたファイルをデータにぶちこんでいく作業。
ここでは名前が既存データになければ登録していくという仮定になっている。

/app/models/user.rb
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

ほとんどコピーみたいなもんなんで、すみません。
エンコード直すのとかも入れてもいいかもだけど、まぁとりあえず。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1