マスタデータ作成時の問題点
ということで、xlsをyamlに変換して、さらにyamlをseedとしてDBに投入するためのgemを作りました。(マスタデータの編集時はxlsとyamlを同時にcommitする想定)
元々padrinoで使う予定だったのでpadrinoを想定してますが一応railsも対応してます。
使い方
bundle exec rake heart_seed:init
で設定ファイルやディレクトリが作られる- xlsを作る
bundle exec rake heart_seed:xls
でxlsをyamlに変換bundle exec rake db:seed
orbundle exec rake heart_seed:db:seed
でyamlからDBに投入TABLES
やCATALOGS
がオプションで使えます(後述)
Railsじゃなかったら下記を Rakefile
に追加してください
require 'heart_seed/tasks'
仕様
githubにも英語で書いていますが重要な事なので日本語でも失礼します
xls/xlsx のフォーマット
例えばこんなシートがあった時は
id | title | description | created_at | this is dummy | |
---|---|---|---|---|---|
1 | title1 | description1 | 2014/6/1 12:10 | foo | |
2 | title2 | description2 | 2014/6/2 12:10 | baz |
- シート名 = テーブル名に対応
- DBに存在しないテーブルは無視される
- 1行目がヘッダ行でカラム名をいれる
- 途中に空のセルがあった時はそこより右側は全部無視される
- 2行目以降が実際のレコード
- タイムスタンプは ActiveSupport::TimeWithZone が使われます。
- roo 単体だとExcelのタイムスタンプはUTCとして解釈されるのでheart_seedの中でごにょごにょしてます
yamlのフォーマット
上記の例だとこんな感じのyamlが作られます(ActiveRecord::FixtureSet と同じフォーマット)
--- articles_1: id: 1 title: title1 description: description1 created_at: '2014-06-01 12:10:00 +0900' articles_2: id: 2 title: title2 description: description2 created_at: '2014-06-02 12:10:00 +0900'
catalog
catalogとは似たようなテーブルのグループみたいなものです。
config/heart_seed.ymlにこんな感じで書きます。
catalogs: user: - users - user_profiles
下記のように実行することでusesとuser_profilesの2つのテーブルに対して db:seed
できます
CATALOGS=user bundle exec rake db:seed
production(本番)への db:seedは TABLEかCATALOGどっちか必須
db:seed にオプション無ければ全テーブルにseedを適用しますが、productionでこれをやると意図せずデータを書き換えたり巻き戻ったりするかもしれないので出来ないようにしています。
シャーディング(垂直分割)対応
大規模なアプリだと 1つのデータベースを複数のシャードに分割してるかもしれませんが、そういう時に db/seeds.rb に
SHARD_NAMES = %W( #{Rails.env} shard_#{Rails.env} shard2_#{Rails.env} ) HeartSeed::DbSeed.import_all_with_shards(shard_names: SHARD_NAMES)
こういう風に書くことで、全てのシャードにseedを投入することができます。(マスタデータは使用頻度高いので全てのシャードからJOINできるようにする想定)
頑張ったこと
- database_rewiinder でのシャーディングのテスト頑張った
- https://github.com/sue445/heart_seed/blob/master/spec/db/setup.rb
- テスト手法を確立するだけで1〜2週間くらい悩んだw
名前の由来
seed = 種 = 「こころの種(heart seed)が生まれそうですぅ〜」