【rails】csvファイルのデータをインポートしてDBに保存する

##前提条件

Rails 5.2.4.2

インポートするcsvファイル：house_data.csv

```terminal:house_data.csv
first_name,last_name,city,num_of_people,has_child
Carolyn,Flores,London,2,Yes
Jennifer,Martinez,Cambridge,3,No
  ...
```

## 手順

#### コントローラ／モデルの作成
```terminal:terminal
rails g controller Houses
rails g model User first_name:string last_name:string city:string
num_of_people:integer has_child:string
rails db:migrate
```

#### ruby標準ライブラリcsvを追加
```ruby:config/application.rb
require 'rails/all'
require 'csv'
```

#### gemの追加
csvファイルを読み込むためのgem ```roo```を追加する。

```ruby:Gemfile
gem 'roo'
```
```terminal:terminal
$ bundle install
```

#### ビューにcsvアップロードのためのフィールドを追加

```ruby:app/views/houses/index.html.haml
      = form_tag import_houses_path, multipart: true do
        = file_field_tag :file
        = submit_tag "インポート"

  %table
    %thead
      %tr
        %th
          ID
        %th
          FirstName
        %th
          Lastname
        %th
          City
        %th
          num_of_people
        %th
          has_child
    %tbody
      - @houses.each do |house|
        %tr
          %td
            = house.id
          %td
            = house.first_name
          %td
            = house.last_name
          %td
            = house.city
          %td
            = house.num_of_people
          %td
            = house.has_child
```

#### コントローラにアクションを追加
```rails:app/controllers/houses_controller.rb
  def import
    House.import(params[:file])
    redirect_to houses_url
  end
```

#### ルーティングを設定

```ruby:config/routes.rb
Rails.application.routes.draw do
   resources :houses do
    collection { post :import }
  end
end
```

#### ルーティング確認
```terminal:terminal
% rails routes
                   Prefix Verb   URI Pattern                                                                              Controller#Action
            import_houses POST   /houses/import(.:format)                                                                 houses#import
                   houses GET    /houses(.:format)                                                                        houses#index
                          POST   /houses(.:format)                                                                        houses#create
                new_house GET    /houses/new(.:format)                                                                    houses#new
               edit_house GET    /houses/:id/edit(.:format)                                                               houses#edit
                    house GET    /houses/:id(.:format)                                                                    houses#show
                          PATCH  /houses/:id(.:format)                                                                    houses#update
                          PUT    /houses/:id(.:format)                                                                    houses#update
                          DELETE /houses/:id(.:format)                                                                    houses#destroy

```

####モデルにimportメソッドを記載
```app/models/house.rb
class House < ApplicationRecord
  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      house = find_by(id: row["id"]) || new
      house.attributes = row.to_hash.slice(*updatable_attributes)
      house.save
    end
  end
  def self.updatable_attributes
    ["id", "first_name", "last_name", "city", "num_of_people", "has_child"]
  end
end

```

## 結果

localhost:3000/houses
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564329/c4dc3cb2-daaa-d65e-441e-62150ebcd42c.png)


##### 参考文献
https://qiita.com/seitarooodayo/items/c9d6955a12ca0b1fd1d4