【Rails】フィクスチャファイルからCSVファイルを読む込む

# はじめに
MinitestのフィクスチャファイルからCSV形式で書かれたデータを読み込むソースコードを読解した記録です。

- フィクスチャ
    -  事前に定義したデータをテスト実行直前にtestデータベースに導入できる
    -   ひとつのモデルにつき一つのフィクスチャファイルが作成され、test/fixtures/ディレクトリの下に置かれる
    -   YAML形式で記述される
- CSV
    - 「Comma Seperated Value」の略
    -  値や項目をカンマ（,）で区切って書いたデータ形式
    -  互換性と汎用性が高い

## 環境
- Rails6.1.7
- Ruby2.7.8

## testディレクトリの構造
```
test/
(省略）
 ├─ fixtures
 │   └─ hoge.yml
 │   └─ fuga.yml
 └─  └─ piyo.yml
 ├─ data
 │   └─ hoge.csv
 │   └─ fuga.csv
 └─  └─ piyo.csv
```
- fixruresディレクトリ
    - yaml形式のファイルを配置する
    -  ファイル名が対応するdataディレクトリのCSVデータを読み込む
- dataディレクトリ
    - CSV形式のデータが書かれたファイルを配置する
```test/data/hoge.csv
id,name,price,size
1,foo,100,M
2,bar,500,L
3,baz,200,S
```
# ソースコード例
```test/fixtures/hoge.yml
<% require 'csv' %>

<% CSV.foreach("test/data/#{File.basename(__FILE__).split('.').first}.csv", headers: true) do |row| %>

# __FILE__: test/fixtures/hoge.yml
# File.basename(__FILE__): hoge.yml
# "test/data/#{File.basename(__FILE__).split('.').first}.csv": "test/data/hoge.csv"
# CSV.foreach("test/data/#{File.basename(__FILE__).split('.').first}.csv", headers: true) do |row| ~ end : test/data/hoge.csvの各行をブロック変数rowに渡す、一行目はヘッダとして扱う

# 下記でYaml形式に整形する
<%= row['id'] %>:
<% row.headers.each do |column| %>
  <%= column %>: <%= row[column] %>
<% end %>
<% end %>
```
### 読解①
```yml
<% require 'csv' %>

<% CSV.foreach("test/data/#{File.basename(__FILE__).split('.').first}.csv", headers: true) do |row| %>

# <%= row['id'] %>:
# <% row.headers.each do |column| %>
  # <%= column %>: <%= row[column] %>
# <% end %>
<% end %>
```
- `require 'csv'`
    - CSVライブラリを読む込む 
- `CSV.foreach(path, options = Hash.new) do |row| ~ end`
    -  CSVファイルのパスを指定し、各行を読み込んでブロック変数rowに渡す
    -  オプションには `CSV.new` と同じオプションを指定できる

   - `headers: :first_row` もしくは　`headers: true` をオプションに指定するとCSV ファイルの一行目をヘッダとして扱う

- `__FILE__`
  - 擬似変数
  - 現在のソースファイル名
  - フルパスとは限らないため、フルパスが必要な場合は `File.expand_path(__FILE__)` とする必要がある
  - 実行している「ファイル名のみ」を取得する場合は `File.basename(__FILE__)` で取得する
   
  
https://docs.ruby-lang.org/ja/latest/method/CSV/s/foreach.html

https://docs.ruby-lang.org/ja/latest/method/CSV/s/new.html

### 読解②
```yml
#<% require 'csv' %>

#<% CSV.foreach("test/data/#{File.basename(__FILE__).split('.').first}.csv", headers: true) do |row| %>

<%= row['id'] %>:
<% row.headers.each do |column| %>
  <%= column %>: <%= row[column] %>
<% end %>
#<% end %>
```
- `row['id']`
  - idの値を取得する
```
irb(main):014:1* CSV.foreach("hoge.csv", headers: true) do |row|
irb(main):015:1*   puts row['id']
irb(main):016:0> end
1
2
3
```

- `row.headers` 
  - ヘッダにあたるキーを取得する
```
irb(main):002:1* CSV.foreach("hoge.csv", headers: true) do |row|
irb(main):003:1*   puts row.headers
irb(main):004:0> end
id
name
price
size
id
name
price
size
id
name
price
size
```

- 下記のように、yaml形式で出力される
```
irb(main):020:1*  CSV.foreach("test.csv", headers: true) do |row|
irb(main):021:1*    puts "#{row['id']}:"
irb(main):022:2*    row.headers.each do |column|
irb(main):023:2*      puts "#{column}: #{row[column]}"
irb(main):024:1*    end
irb(main):025:0>  end
1:
id: 1
name: foo
price: 100
size: M
2:
id: 2
name: bar
price: 500
size: L
3:
id: 3
name: baz
price: 200
size: S
```

# おわりに
サンプルデータを大量に作成したい場合には下記のようなERBのコードも活用できます。データのタイプによって使い分けたいと思います。
```yml
<% 1000.times do |n| %>
  user_<%= n %>:
    username: <%= "user#{n}" %>
    email: <%= "user#{n}@example.com" %>
<% end %>
```
https://railsguides.jp/testing.html#erb%E3%81%A7%E3%83%95%E3%82%A3%E3%82%AF%E3%82%B9%E3%83%81%E3%83%A3%E3%81%AB%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E5%9F%8B%E3%82%81%E8%BE%BC%E3%82%80