困ったこと
Railsのseed_fu、こういう風にidなどprimary keyを書くのを巷でよく見かけます。
User.seed do |s|
s.id = 1 # ←
s.name = "鈴木一朗"
s.email = "ichiro@example.com"
end
User.seed do |s|
s.id = 2 # ←
s.name = "鈴木二郎"
s.email = "jiro@example.com"
end
idなんて自動採番されるんだから、書く必要なくない?...ほら、削除してもデータ作れるじゃん!と無邪気にどや顔していたのですが、青二才でした。
確かにデータは作れます。しかしながら、seed_fuがいいのは、2回目以降流す時に、変更点だけを追加、または更新してくれるところ。primary keyを指定してあげないと、seed_fuは既存データか新規データかを判別できず、新しいデータをcreateしてしまいます。上記の例で言うと、鈴木一朗、鈴木二朗がダブってできてしまいます。
でもそうしたくない時があると思います。
とほほ。じゃあidを書いてあげて、インクリメントしていくしかないのかと諦めかけました。こんな感じで↓
id = 1
User.seed do |s|
s.id = id
s.name = "鈴木一朗"
s.email = "ichiro@example.com"
end
id += 1
User.seed do |s|
s.id = id
s.name = "鈴木二郎"
s.email = "jiro@example.com"
end
もっといい感じのやり方
ちゃんとドキュメントを読んだら、もっとスマートな方法のヒントが書いてありました。
seedメソッドの引数に「このカラム見てね、あったら新しく作らないでね」と教えておけば、そのカラムで同じデータがDBに既にある場合、それは既存のデータとみなしてくれます。User.seed(:name)
という具合です。
User.seed(:name) do |s|
s.name = "鈴木一朗"
s.email = "ichiro@example.com"
end
User.seed(:name) do |s|
s.name = "鈴木二郎"
s.email = "jiro@example.com"
end
上の例では、DBのnameカラムの中で同じものがあればそれは既存のデータと見なされ、新しくcreateされることはありません。
複数のカラムでデータを特定したいときは、User.seed(:name, :email)
と引数を複数指定してあげることもできます。
スマートで、ちょっとハッピー。
余談
本記事のタイトルの文字数が長いです。
seed_fuのseedメソッドの引数を活用すれば、似たデータが重複して新規作成されることもないし、idをわざわざ書く必要もないぞと気づいた
70文字です。
でもQiitaのタイトルは255文字まで行けるそうです。