seed_fuでCSVファイルからデータを作成する

#概要

Railsで初期データを作成する場合、seed_fuは便利なのですが、ユーザに初期データ作成を以下のような`seed_fu`の形式で依頼するのは難しいものがあります。

```rb:user.rb
# coding: utf-8

User.seed do |s|
  s.id = 1
  s.name = '山田 花子'
  s.email = 'yamada@hogehoge.hoge'
  s.groups = Group.where(:name => ['部署１','部署２'])
end
```

そこで、ユーザにはCSVファイルでデータを作成してもらって、それを読み込むようにしてみます。

基本的な書き方は以下のようになります。

```rb:db/fixtures/import.rb
require 'csv'

# インポートファイルを読み込む
def import_read( file_name )
  lines = CSV.read("db/fixtures/#{Rails.env}/#{file_name}")
  lines.unshift([])  # index 0番目は空行を入れてスキップさせる

  lines.each_with_index do |line, idx|
    next unless line.length > 0
  
    yield(line, idx) if block_given?
  end
end

# CSVファイルの取込
import_read('hoge.csv') do |line, idx|
  Hoge.seed do |s|
    s.id      = idx
    s.column1 = line[0]
    s.column2 = line[1]
  end
end
```

#サンプル
では、実際にどのように記述していくか、サンプルを掲示します。
テーブル構造などは、[こちら](http://qiita.com/takaki_k/items/31a3be1c630b26080c17)を参照してください。

今回、`development`環境用に作成していますが、`production`、`staging`と環境別にフォルダを分けてデータファイルを用意します。

##取り込むCSVファイル
```csv:db/fixtures/development/ヘッダ.csv
文房具
自転車
書籍
```
```csv:db/fixtures/development/詳細.csv
文房具,えんぴつ,3
文房具,ボールペン,145
文房具,定規,-5
自転車,ビアンキ,3
自転車,GT,25
```
```csv:db/fixtures/development/部署.csv
総務部,組織の事務を扱う,
秘書課,役員を補佐する,総務部
広報課,情報発信を行う,総務部
人事部,社員情報を管理する,
人事一課,,人事部
人事二課,,人事部
```
```csv:db/fixtures/development/ユーザ.csv
山田 花子,yamada@hogehoge.hoge,秘書課
鈴木 一郎,suzuki@hogehoge.hoge,人事二課,広報課
田中 太郎,tanaka@hogehoge.hoge,人事一課
佐藤 次郎,sato@hogehoge.hoge,人事部,広報課
```
```csv:db/fixtures/development/ゲスト.csv
井上 直太郎,inoue@hogehoge.hoge
大谷 健太郎,ootani@hogehoge.hoge
松本 浩太郎,matsumoto@hogehoge.hoge
```

##インポート用のRubyファイル

**共通メソッド**
今回、seed_fuを意識していますが、他でも使えるように、libに共通メソッドとして作成しています。

```rb:lib/import.rb
require 'csv'

#
# =データのImportをサポートするメソッド群
#
# Author::  Takaki-K
# Version:: 0.0.1
#
module Import

  # == CSVのインポートファイルを読み込む
  # 指定されたCSVファイルを読み込み、読み込んだデータを１行単位で配列に格納し、ブロックへ渡す。
  # ブロックへは、データ（配列）、Index（1～）を渡す。
  #
  # === 引数
  # - file_path ファイルパス
  # - file_name ファイル名称（省略可 デフォルト値=nil）
  # - header    ヘッダの有無（省略可 デフォルト値=false）
  #
  def self.csv_read( file_path, file_name=nil, header=false )
    file_path = File.expand_path(file_name, file_path) unless file_name.nil?
    
    lines = CSV.read(file_path)
    lines.unshift([]) unless header  # headerが無い場合は、index 0番目に空行を入れてスキップさせる

    lines.each_with_index do |line, idx|
      next if     idx == 0         # ヘッダ行は読み飛ばす
      next unless line.length > 0  # データが無い行は読み飛ばす

      yield(line, idx) if block_given?
    end
  end

end
```

**seed_fu用の読み込みファイル**
種類別に読み込みファイルを作成しています。

```rb:db/fixtures/data_resources.rb
require "#{Rails.root}/lib/import.rb"

# =データの取込

# データファイルを保存しているフォルダ
data_folder = "#{Rails.root}/db/fixtures/#{Rails.env}"

# ==ヘッダ情報の取込
Import.csv_read(data_folder, 'ヘッダ.csv') do |line, idx|
  Header.seed do |s|
    s.id    = idx
    s.title = line[0]
  end
end


# ==詳細情報の取込
Import.csv_read(data_folder, '詳細.csv') do |line, idx|
  Detail.seed do |s|
    s.id     = idx
    s.header = Header.find_by_title(line[0])
    s.name   = line[1]
    s.stock  = line[2]
  end
end
```
```rb:db/fixtures/human_resources.rb
require "#{Rails.root}/lib/import.rb"

# =人事情報の取込

# データファイルを保存しているフォルダ
data_folder = "#{Rails.root}/db/fixtures/#{Rails.env}"

# == 部署情報の取込
Import.csv_read(data_folder, '部署.csv') do |line, idx|
  Group.seed do |s|
    s.id    = idx
    s.name  = line[0]
    s.description = line[1]
    s.group = Group.find_by_name(line[2])
  end
end


# == ユーザ情報の取込
Import.csv_read(data_folder, 'ユーザ.csv') do |line, idx|
  User.seed do |s|
    s.id    = idx
    s.name  = line[0]
    s.email = line[1]
    line.shift(2)
    s.groups = Group.where(:name => line)
  end
end

# == ゲスト情報の取込
Import.csv_read(data_folder, 'ゲスト.csv') do |line, idx|
  Guest.seed do |s|
    s.id    = idx
    s.name  = line[0]
    s.email = line[1]
  end
end
```

#取込
ここまでできれば、取り込むだけです。

`bundle exec rake db:seed_fu RAILS_ENV=development`