概要
ビジネスサイドの人とサービス作るお仕事してるとよくスプレッドシートでマスターデータを受け取ることがある。
なんで、スプレッドシートのデータをどう管理してDBへ格納するか考えた結論のメモ。
やったこと
- スプレッドシートをtsvで出力
- tsvからDBへ一時的に格納
- この時test用DBを使うことで他の環境を汚さないようにする
- DBへ格納されたレコードをseedファイルとしてエクスポート
- 環境へのインポートは
rake db:seed
で行う。- seed内では
create!
ではなくfirst_or_create!
メソッドを使うことで冪等性を担保する
- seed内では
環境
環境はすべてdockerへ固めて実行している。
また、以下の全てのコマンドは docker-compose
内で実行している。
手順
スプレッドシートの用意
適当に id
と name
の存在するスプレッドシートを用意
スプレッドシートからtsvを出力
スプレッドシートをcsvで出力すると改行コードがおかしなことになって扱いが面倒なので、tsvでエクスポートする。
こんな感じのファイルがエクスポートされる。
id name 123 hoge 456 fuga 789 piyo
Gemfileへgemの追加
gem 'seedbank' gem 'seed_dump'
seedbank
はseed管理の拡張を行う
seed_dump
はDBのデータをファイルへエクスポートを行う
Taskの作成
$ bundle exec rails g task master
Taskの編集
require 'csv' namespace :master do desc 'tsvからDBへインポートを実行. e.g. $ MASTER_FILE=./dist/master.tsv RAILS_ENV=test bundle exec rake master:import' task import: :environment do exit unless file = ENV['MASTER_FILE'] output_file = ENV['OUTPUT_FILE'] || "db/seeds/master.seeds.rb" sh "bundle exec rails db:migrate:reset" csv = CSV.read(file, headers: true, col_sep: "\t") csv.each do |data| Master.create( id: data[0], name: data[1] ) end sh "bundle exec rake db:seed:dump FILE=#{output_file} MODEL='Master' EXCLUDE='created_at,updated_at'" #XXX: ここで first_or_create に変換しないと2度以上 `rake db:seed` が実行できなくなる sh "cat #{output_file} | sed -e 's/create!/first_or_create!/' > #{output_file}" sh "bundle exec rails db:migrate:reset" end end
seedデータの生成
$ RAILS_ENV=test MASTER_FILE=dist/master.tsv bundle exec rake master:import
データのインポート
$ bundle exec rake db:seed