gem ancestry + seedファイルを利用した、データベースへの複数カラム挿入


本記事について

Ruby on Railsのseedファイルを使って、ancestryのデータを挿入するとき、カラムを複数同時に挿入したいと思い、その実装ができたので解説させていただきます。
(とあるプログラミングスクールのカリキュラムによって、某フリマアプリのカテゴリーに関する記事がたくさんありますが、そちらはカラムが1つしかなかったため投稿しようと考えました。)

目的

  1. seedファイルを使ってデータベースを作成すること
  2. データベース作成時に複数のカラムを同時に生成すること

参考資料

Qiita参考記事
【Rails】ancestryで簡単に多階層型データの作成し呼び出す
railsのseedの書き方いろいろ
Rails・seedファイルを分割して管理する

事前準備

ancestryの基本的な導入方法はたくさん記事があるので、割愛させていただきます。
gemのインストール、モデルの定義、テーブルの作成まで終わったものとします。

実践

今回はfood(食材)のテーブルを作成し、seedファイルで複数のカラムを同時に挿入してみます。
完成後のテーブルはこのような感じです。

ancestryのgemを使っているので、「ancestry」のカラムはこのように自動的に入ります。
今回実践するカラムの同時挿入は、「name」と「description(説明)」です。
ではいきましょう。

seedファイルにデータの書き込み

テーブルに登録するデータを書き込み、データを作成するようにcreateメソッドで定義してあげます。
今回はこのようになります。

db/seeds.rb
parent_array = [
  {name: "野菜", description: "健康を保つための栄養が取れる食材"},
  {name: "果物", description: "食を彩る栄養価も高い食材"}
]

vegetable_child_array = [
  {name: "根菜類", description: "根っこの部分を食べる野菜"},
  {name: "葉菜類", description: "葉っぱの部分を食べる野菜"}
]

vegetable_grandchild_array = [
  [ # 野菜 >> 根菜類
  {name: "大根", description: "火を通すと甘味が増す野菜"},
  {name: "にんじん", description: "鮮やかな橙色の野菜"}
  ],[ # 野菜 >> 葉菜類
  {name: "ほうれん草", description: "鉄分が豊富な野菜"},
  {name: "レタス", description: "シャキシャキとした食感が特徴の野菜"}
  ]
]

parent = Food.create(parent_array[0])
vegetable_child_array.each_with_index do |child,i|
  child = parent.children.create(name: child[:name], description: child[:description])
  vegetable_grandchild_array[i].each do |grandchild|
    child.children.create(name: grandchild[:name], description: grandchild[:description])
  end
end


fruit_child_array = [
  {name: "仁果類", description: "花の先端部分が膨らんで果実になる果物"},
  {name: "柑橘類", description: "ビタミンCやクエン酸を多く含む果物"}
]

fruit_grandchild_array = [
  [ # 果物 >> 仁果類
  {name: "りんご", description: "甘い蜜を含んだ果実"},
  {name: "なし", description: "水分を多く含んだ甘い果物"}
  ],[ # 果物 >> 柑橘類
  {name: "みかん", description: "橙色の甘い果物"},
  {name: "レモン", description: "酸味が特徴的な果物"}
  ]
]

parent = Food.create(parent_array[1])
fruit_child_array.each_with_index do |child,i|
  child = parent.children.create(name: child[:name], description: child[:description])
  fruit_grandchild_array[i].each do |grandchild|
    child.children.create(name: grandchild[:name], description: grandchild[:description])
  end
end

少し長いですが、このようになります。
記述の方法はいろいろあるので、一例と思って見てください。

ここで大事なのが、createする時に、

~ xx.create(name: child[:name], description: child[:description])

と記述することで、カラムを指定して登録できます。実は結構簡単でした。

データの挿入

続いて、データを挿入していきます。
ターミナルで、以下のコマンドを実行します。

$ rails db:seed

これで、エラーメッセージが出なければ、データが挿入されているのができるはずです。
データの読み込みが成功したときは、何もメッセージが出ないはずです。

[追記]
データの読み込みが成功したときは何もメッセージが出ませんが、
メッセージが出なくても読み込みに失敗している時がありました。
そんな時は、createメソッドをcreate!メソッドにすることでエラーの内容が見れるようになります。

# create!メソッド使用時
$ rails db:seed

=> rake aborted!
ActiveRecord::RecordInvalid: バリデーションに失敗しました: Userを入力してください

上記の例は、modelにアソシエーションの記述をした状態だったため、読み込みがされていないのに何もメッセージが出ていませんでした。特定するのには、create!メソッドが便利なので使うことをおすすめします。

注意点

seedファイルを読み込むときは、テーブルに作成済みのレコードがないか確認してから行いましょう。
重複するデータがあるとエラーで弾かれてしまいます。

最後に

seedファイルの読み込みは、慣れるまで結構大変に感じました。
エラーの原因がわかりにくいので、根気よくがんばってください!