Railsのseeds.rbに冪等性を持たせるためのスクリプトを書いた

Railsでテストデータやマスタデータを作成するために、seeds.rbを使うと思います。
しかし、そのまま使うのでは不便だったので、以下の条件を満たすように改良しました。

・データベースレコードをIDで検索し、見つかれば既存のデータをseeds.rbに定義されたデータで更新
・データベースレコードをIDで検索し、見つからなかった場合、seeds.rbに定義されたデータを挿入
・seeds.rbに定義された以外のIDのレコードを全削除

例えばitem_kindとuserテーブルがある場合、以下のようになります。

def insert_and_delete_unnecessary_record(model_snake_case_name, seed_data)
  current_model = eval(model_snake_case_name.camelize)
  current_ids = current_model.all.ids
  inserted_ids = []
  seed_data.each do |row|
    inserted_ids << row[:id]
    new_seed_data = current_model.find_or_initialize_by(id: row[:id])
    row.delete(:id)
    row.each do |key, value|
      value = "'#{value}'" if value.is_a? String
      value = 'nil' if value == nil
      eval("new_seed_data.#{key} = #{value}")
    end
    new_seed_data.save!
  end

  current_ids.each do |id|
    unless inserted_ids.include?(id)
      current_model.destroy(id)
    end
  end
end

seed_item_kind = [
    {id: 1, name: '家電'},
    {id: 2, name: 'ゲーム'},
    {id: 3, name: 'スポーツ'},
    {id: 4, name: 'パソコン'}
]

insert_and_delete_unnecessary_record('item_kind', 'seed_item_kind')


seed_user = [
    {id: 1, name: '田中', age: 20},
    {id: 2, name: '山中', age: 30},
    {id: 3, name: '佐藤', age: 40},
    {id: 4, name: '小田', age: 26}
]

insert_and_delete_unnecessary_record('user', 'seed_user')

insert_and_delete_unnecessary_record関数をseeds.rbの一番上にコピペします。
そして、変数に配列としてカラムをキー、バリューをそのカラムの値として入れます。
最後に、以下のようにしてinsert_and_delete_unnecessary_record関数を呼び出せば、配列として定義したデータがそのままデータベースに登録されます。

insert_and_delete_unnecessary_record(テーブル名, 配列を定義した変数名)

ちなみに、seedbankを使うと
・ファイルを分割できる
・データ間の依存を管理できる
・環境ごとにseedファイルを分けられる

ができるので、上記のスクリプトと合わせて使うと便利です。

投稿者プロフィール

スカイブロガー

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Time limit is exhausted. Please reload CAPTCHA.