RoR+MySQLの環境へデータ投入


今日の目的は、csvを直接テーブルへ投入したい。
見つけたのはこの2つのやり方。


1、http://blog.livedoor.jp/maru_tak/archives/50604155.html  fixturesを使う方法。
2、id:hichiriki:20081019    csv一気読み込みをrakeタスクでやる方法。ファイル数が多いと有益。


1-(1) *.csvを test/fixture/へコピーし、"テーブル名.csv"へリネームする。
1-(2) 一行目にヘッダを記載。カンマ区切り。idは勝手に振ってくれるとのこと、につき無視。
1-(3) rake db:fixtures:load

2-(1) ファイルを用意するのは、1と同じ。2のやり方ではヘッダ部は記載しないこと(読み込まれてしまう)。
2-(2) 自分の環境に合わせて、lib/task/load_data.rake を作る。私のデータでは、ENCLOSEDの指定は不要だ。
2-(3) rake load_data


まず、1で試したものの、フィールドがNULLのままでデータが投入されてない。理由不明。【←自己レス】次のトピックで書くように、*.ymlがあると*.csvに優先されてfixtures:loadされるためのようだ。

ということで、今回は2でやってみる。

# lib/tasks/load_data.rake
require "environment"

task :load_data do
dir = "#{RAILS_ROOT}/test/fixtures"
Dir.open(dir).each do |f|
next unless /\.csv$/ =~ f
load_csv(dir, File.basename(f, ".csv"))
end
end

def load_csv(dir, t)
con = ActiveRecord::Base.connection
$stderr.write "deleting #{t} ... "
con.execute "delete from #{t}"
$stderr.write "done.\n"
$stderr.write "loading #{t} ... "
con.execute "LOAD DATA INFILE '#{dir}/#{t}.csv' INTO TABLE #{t} FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n';"
$stderr.write "done.\n"
end

> rake load_data
(in /RoR_test/B5)
deleting b5s ... done.
loading b5s ... done.

実行する都度、削除と投入を行うようだ。
また、フィールドをdb/migrate/xxx_create_B5s.rbで設定した場合、勝手に作られるID (Key=PRI,Extra=auto_increment)は一旦deletingしても番号はインクリメントされた次の数から始まり、created_at,updated_atはNULLのままです。
しかもidのフィールド位置が最初なので、csvが一つずれて読み込まれるため、そこを調節してやる必要がある。


以下の記述もためになる。
http://api.rubyonrails.org/classes/Fixtures.html  読み込めるファイル形式の説明