←Rails 6で認証認可入り掲示板APIを構築する #7 update, destroy実装
seedとは
開発中にテストデータが必要な時、都度rails c
やらcreate actionを叩いてレコード作るのは手間です。
そこで、コマンドを叩くだけであらかじめ設定しておいたレコードを、50だろうが1000だろうが簡単に作れるseedを取り入れます。
ファイル作成とロード
rails seedだけでググると大抵db/seeds.rbに直書きばかり出てきますが、modelが多くなると管理がしづらくなります。
そこでファイルを分割し、db/seeds.rbからrequireで呼ぶ形式にします。
こうすることで追加削除時の管理がしやすくなりますし、seedはファイル指定で実行することもできるので便利です。
$ mkdir db/seeds
$ touch db/seeds/post_seeds.rb
# frozen_string_literal: true
seed_models = %i[post]
seed_models.each do |model|
require "./db/seeds/#{model}_seeds"
end
# frozen_string_literal: true
unless Post.exists?
20.times do
Post.create!(subject: "hoge", body: "fuga")
end
end
今後seed対象のmodelが増えることを予想し、seed_modelsという変数に追加していくことで外部ファイル読み込みをするようにします。
ディレクトリ走査することで都度db/seeds.rbを変更しなくても良い作りにできるのですが、postモデルの前に今後作るuserモデルのレコードが存在していないといけない等の依存関係が発生するので、手動で実行順を弄れるように書いています。
post_seeds.rbの中身は単純にPost.create!
を20回実行しているだけです。
!
を付けることによりバリデーションエラーで登録できなかった際に例外が投げられるので、気付いたらレコードが生成されていなかった事態を防げます。
$ rails db:reset
$ rails db:seed
$ rails c
[1] pry(main)> Post.count
(1.1ms) SELECT COUNT(*) FROM "posts"
=> 20
db:resetすることでテーブルを全dropし再生成。これでレコードがある時のみ動くseedが実行されます。
そしてdb:seedすることで、20レコードが追加されていることが確認できます。
Fakerの導入
レコードができたのはいいのですが全部subjectがhoge, bodyがfugaになっています。
このままだと、何かしらの原因でAPIから取得したら同一レコードが紛れていたりしても気付きづらくなります。
とはいえ完全ランダムな文字列を都度作るのも手間だし…ということで、役立つのがFakerです。
とりあえず入れてみましょう。
...
group :development, :test do
...
+ "faker"
end
...
$ bundle
試しに使ってみましょう。
$ rails c
[1] pry(main)> Faker::Name.unique.name
=> "Miss Porter Kovacek"
[2] pry(main)> Faker::Name.name
=> "Felicita Durgan"
[3] pry(main)> Faker::Name.name
=> "Yong Weissnat"
[4] pry(main)> Faker::Name.name
=> "Sandie Oberbrunner"
こんな感じに、実行のたびにランダムな名詞や文章を自動で返してくれるものです。
デフォルトで定義されている語句はGithubで確認すると良いです。
人名や動物、住所や電話番号等だけでなく、映画、漫画、ゲーム、ドラマ、音楽なんかもあります。ポケモン名とかONE PIECEの悪魔の実とかまでありますね。
seedsにFakerを入れる
# frozen_string_literal: true
unless Post.exists?
20.times do
- Post.create!(subject: "hoge", body: "fuga")
+ Post.create!(subject: Faker::Lorem.word, body: Faker::Lorem.paragraph)
end
end
$ db:reset
$ db:seed
$ rails c
[1] pry(main)> Post.all
Post Load (0.4ms) SELECT "posts".* FROM "posts"
=> [#<Post:0x000000000636cbe8
id: 1,
subject: "quos",
body: "Earum numquam qui. Impedit autem molestias. Ipsum adipisci eos.",
created_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00,
updated_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00>,
#<Post:0x00000000063b5be0
id: 2,
subject: "vero",
body:
"Impedit distinctio saepe. Adipisci cupiditate officiis. Vel et deleniti.",
created_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00,
updated_at: Sun, 06 Sep 2020 15:36:27 UTC +00:00>,
ランダムなsubject, bodyのレコードができていることが確認できます。
Fakerを日本語化する
せっかく入れたのに英語だと日本語サイトを作る上で不便なので、ローカライズしましょう。
db:seedはdev環境で実行するので、dev環境の時にFakerを日本語化してみます。
Rails.application.configure do
...
+ Faker::Config.locale = "ja"
end
常に日本語化が嫌なのであれば、Faker::Config.locale = "ja"
をdb/seeds/post_seeds.rbに入れてもOKです。
その後再度seedを実行します。
$ rails db:reset
$ rails db:seed
$ rails c
[1] pry(main)> Post.all
Post Load (0.3ms) SELECT "posts".* FROM "posts"
=> [#<Post:0x0000000006480b88
id: 1,
subject: "いく",
body: "警官総括大尉。めいしぼきんかたみち。伝統徳川超〜。",
created_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00,
updated_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00>,
#<Post:0x00000000064fb928
id: 2,
subject: "フランス語",
body: "〜系けいかん先週。うえる自宅そだてる。店舗にんい高値。",
created_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00,
updated_at: Sun, 06 Sep 2020 15:45:27 UTC +00:00>,
無事に日本語化されていますね。
なお、日本語化されているものはGithubで確認できます。逆に言えばこの中に無いものは英語のままです。