RailsにFixturesで初期データを入れるためのyamlをCSVから作るスクリプト


Railsのデータベースにデータを投入する方法はfixtures用のyamlファイルを作って、railsコマンドで入れる方法などがよく知られています。
ですが、現実的にはExcelなどで元データを用意してCSV等で扱うことが多いと思われます。
yamlコンバータなども試してみたけどfixtures keyを入れるのがうまくいかなかったので、自分で作りました。
エスケープ文字の処理とかなにもやってないので、元データがそういうものを扱う場合は適宜加工してください。

たとえば、1行目にカラム名が入ったこんな感じのCSVファイルがあったとして。

fruits.csv
id,item,price
1,りんご,100
2,みかん,80
3,バナナ,60
4,メロン,2000
5,いちご,300

Fixturesで扱うにはこういうyamlファイルが必要になります。

fruits.yml
data1:
  id: 1
  item: りんご
  price: 100

data2:
  id: 2
  item: みかん
  price: 80

data3:
  id: 3
  item: バナナ
  price: 60

data4:
  id: 4
  item: メロン
  price: 2000

data5:
  id: 5
  item: いちご
  price: 300

data1:のところがfixtures keyというやつで、データベースには反映されないけど、レコードごとにハッシュとしてユニークな値をつけなければいけないようです。

スクリプトはこんな感じです。
ExcelからCSVに変換したら、UTF-8でBOMが付いてしまったので、ファイルをopenするときにオプションが付いてます。

csv2yaml.rb
#!/use/bin/env ruby

filename = ARGV[0]

# UTF-8のBOMを消すオプション
file = open(filename, 'r:BOM|UTF-8')

# CSVファイルの先頭行を取得
column = file.gets.chomp.split(",")

# fixtures keyのプレフィックス(data)とそのあとに付けるカウンタ(num)
prefix = "data"
num = 1
str = ""

file.each do |line|
  unless line.strip == ""             ## 空白行を無視する
    str += "#{prefix}#{num}:\n"
    (0 .. column.length - 1).each do |i|
      str += "  #{column[i]}: #{line.chomp.split(",")[i]}\n"
    end
    str += "\n"
    num += 1
  end
end
print str

Shellから実行する時はこんな感じです。

$ ./csv2yaml.rb fruits.csv > fruits.yml

500行くらいのCSVデータの変換して問題なかったし、fixturesでも取り込めたので大丈夫なようです。
カラムが異なる複数のCSVファイルでも変換できました。

yamlのライブラリなどを使えばもっと簡単に作れるかも。