はじめに
先日初めてseedsを使い初期データを登録しましたが、docker-compose upの度にデータが作成されてしまい、気づいたらデータ数がとんでもないことになっていました...。
解決できたのでメモしておきます。
seedsに初期データを書く
今回はname,age,hobbyのカラムを持つusersテーブルに3つ、初期データを登録していきます。
User.create!(
[
{
name: 'Mary',
age: 22,
hobby: 'Cooking'
},
{
name: 'Alice',
age: 25,
hobby: 'Basketball'
},
{
name: 'John',
age: 28,
hobby: 'Soccer'
}
]
)
これでrake db:seedを実行するとデータが作られます。
Docker起動時にデータを作成する
docker-compose upで自動的にデータが作られるように、docker-entrypoint.shに加筆しました。
set -eu
bundle exec rails db:create
bundle exec rails db:migrate
# 以下を加筆
bundle exec rails db:seed
これで無事に初期データが作られました。
……しかし!
これではDockerを起動する度にデータが作られてしまうのです。
重複を防ごうとやってみたこと
・idを振ってcreateにしてみる
→id重複のエラー。
・idを振って、create!をfind_or_create_byにしてみる
User.find_or_create_by(
[
{
id: 1,
name: 'Mary',
age: 22,
hobby: 'Cooking'
},
{
id: 2,
name: 'Alice',
age: 25,
hobby: 'Basketball'
},
{
id: 3,
name: 'John',
age: 28,
hobby: 'Soccer'
}
]
)
これだと、TypeError: no implicit conversion of Hash into Stringエラーが出てしまいました。
first_or_createで解決
色々調べながら、first_or_createを使ってみました。
User.first_or_create(
[
{
id: 1,
name: 'Mary',
age: 22,
hobby: 'Cooking'
},
{
id: 2,
name: 'Alice',
age: 25,
hobby: 'Basketball'
},
{
id: 3,
name: 'John',
age: 28,
hobby: 'Soccer'
}
]
)
2回目以降dockerを立ち上げても、データが重複して作られることはありませんでした。id無しでも試してみましたが、データの重複が無いことを確認できました。
first_or_createは既に同じデータがある場合は作成せず、無ければ新たにデータを作ってくれる。find_or_create_byも同じようなメソッドな気がしていたのですが…
まとめ
・docker起動時にseedsでデータを挿入するにはdocker-entrypoint.shに加筆する。
・データの重複を防ぐにはfirst_or_createを使う。
初心者ですので、間違っている点や他の方法等あればご指摘いただけますと幸いです。