seedデータをmigrationで差分管理できるgem "JewelSeed" を作りました

railsでは標準だとデータベースに必要な初期値の設定にdb/seeds.rbを使います。

ただ、db/seeds.rbだとデータの追加・変更や、再実行などが難しくなりがちです。

で、この辺りを便利にするgemはThe Ruby Toolboxで探すといくつかあります。

Seed-fu

Ruby Toolboxで1位なので、seed-fuを使っている方は多いかと思います。

私も使っていました。

ただ、使っているうちに下記のような不満が出てきました。

  • データ量が増える度に遅くなる
  • 1件ずつインサートしていて、そもそも遅い

もっと使いやすいシード管理は無いのか

シードデータをもっと素早く、効率的に扱えないか・・・と考えてみた所

  • シードデータを差分で管理できる
  • 差分のみをバルクインサートできる
  • もちろん、必要に応じてrollbackもできる

こんな機能が理想だなーってgemを探してみたのですが、無かったので作ってみました。

JewelSeed って何?

jewel_seed はシードを効率良く管理するロストロギアです。

シードデータを差分管理し、activerecord-importを使ってバルクインサートします。

インストール方法

Gemfileにjewel_seedを追加します。

gem 'jewel_seed'

bundler でインストールします。

$ bundle install

シード管理用のテーブルをセットアップします。

$ rake jseed:install

基本的な使い方

JewelSeedのgeneratorを使い、seedを生成します。

$ rails g jseed InitUsers
      create  db/seed_migrate/20140616190258_init_users.rb

ちなみに生成されるseedはこんな感じです。

$ cat db/seed_migrate/20140616190258_init_users.rb
class InitUsers < JewelSeed::Migration
  def up
    # Example import using ActiveRecord Models
    #
    # users = [
    #   User.new(id: 1, name: 'nanoha'),
    #   User.new(id: 2, name: 'fate')
    # ]
    # seed users
  end

  def down
    # Example simple delete records
    #
    # User.delete_all(id: [1, 2])
  end
end

(Exampleのように)seedsに追加・更新の必要なModelsを渡すように実装します。

downはupの変更を戻すような処理を実装します。

変更が終わったらmigrationを実行します。

$ rake jseed:migrate
 - User
#<User id: 1, name: "nanoha", created_at: nil, updated_at: nil>
#<User id: 2, name: "fate", created_at: nil, updated_at: nil>

dump, load

シードデータを全てdb/seeds/*.rbにダンプする事ができます。

$ rake jseed:dump

ダンプしたファイルはこんな内容です。

$ cat db/seeds/users.rb
ActiveRecord::Base.transaction do
User.delete_all
User.import(
["id", "name"],[
[1, "nanoha"],
[2, "fate"],
])
end

もちろん、ダンプした内容をロードする事も出来ます。

$ rake jseed:load

rollback

ロールバックも出来ます。

$ rake jseed:rollback

おわり

とりあえず公開したけど、まだ基本的な機能しかないので、少しずつ拡張はしていきたい。

これから作りたい機能はこんな感じ。

  • rake jseed:rollback STEP=3複数rollback
  • rake jseed:load only=users,booksで指定ロード
  • capistrano対応
  • rspecでのseedを使う場合の対応