テーブルの準備
今回の解説のために使用するテーブル(モデル)を作成していきます!
モデル作成
ターミナルでプロジェクトのフォルダに遷移し、以下のコマンドを実行してモデルとマイグレーションファイルを生成します。
rails g model category
実行後にいくつもファイルが作成されますが、今回使用するのはこれらです。
- db/migrate/YYYYMMDDhhmmss_create_categories.rb
- db/seeds.rb
マイグレーションファイル修正
先ほど生成されたマイグレーションファイルを以下のように修正して nameカラムを追加します。
timestamps は有っても無くてもOKです。
マイグレーション実行
以下のコマンドでマイグレーションを実行します。
rails db:migrate
成功すると、Categoryテーブルが作成され、スキーマファイルに次の内容が追加されます。
これでテーブルの準備は完了です!
seedsファイル
レコード作成
通常のレコード作成では “new” もしくは “create” メソッドを使用してレコードを作成します。
今回は “create” を使用していきます。
seedsファイルに以下の内容を追記します。
そして次のコマンドを実行してレコードを作成します。
rails db:seed
‘rails c’ などで実際にレコードが作成されたことが確認できます。
デリート&インサート
ここで、レコードの削除と作成を繰り返すとidがインクリメントされていってしまうという問題があります。
‘rails c’ で確認すると、さきほど新規で作成した時のレコードidはイチから始まっていましたが、削除と作成を繰り返すうちにidが8から始まってしまっていることがわかります。
これは、DBシステムの裏側で持っているidがインクリメントされ、一度使われたidを再利用しないような設定がデフォルトでされているためです。
しかしこれを解決する方法は単純で、idを指定してあげればOKです。
seedsファイルを以下のように修正しましょう。
これでデリート&インサートによるidの変更は無くなりました。
しかし、この状態で複数回seed実行しようとすると以下のようなエラーになってしまいます。
SQLite3::ConstraintException: UNIQUE constraint failed
これは、テーブルのレコードにおいて、idはユニークである必要がありますが、idを指定したためユニークにならないため、その旨のエラーが出ています。
レコードがなければ作成されるようにする
上記の事象を回避するためには、seeds実行時に、既に同じnameのレコードが存在すればスキップし、無ければ作成するという条件分岐ができればOKです。
しかし、1レコード作成ごとに find して if 文を書くのは大変ですし、少しダサいですよね。
そこで「find_or_create_by」というrailsが提供しているメソッドを使用します!
find_or_create_by
このメソッドは、既に同じレコードが存在していればスキップし、存在していないレコードは新規作成します。
単純に書くと以下のように記述できます。が、少しカッコ悪いですね。。
(これではレコードが増えた時にも find_or_crate_by を増やさなくてはなりません)
配列を用いてコードを工夫してみます。
これでseedsを複数回実行してもエラーが出ず、レコードも重複しないように出来ました!
まとめ
- マスタレコードの定義は id まで定義する
- 重複レコード防止のために find_or_create_by メソッドを使用する
- seeds は配列を用いて書き方を工夫する
コメント