学習記録

アウトプット用に作りました

seed_fuを使って初期データを作成

以前seed_fuを使ってデータを作成したことがあったのですが、そのときには出会わなかったエラーに遭遇したので、記録として残しておきます。

以前書いたブログ seed_fuを使って初期データを作成 - 学習記録



ユーザーテーブルと日記テーブルの初期データを作成していきます。

まず最初にGemfileseed_fugemを追加してbundle installします。

gem 'seed-fu'

seedファイルを置くためのディレクトリを作成します。

$ mkdir db/fixtures
$ mkdir db/fixtures/development
$ mkdir db/fixtures/production
$ mkdir db/fixtures/test

開発環境のUserテーブルとDiaryテーブルにデータを作成していきたいと思います。まずdevelopment配下に下記2つのファイルを用意します。

$ touch db/fixtures/development/users.rb
$ touch db/fixtures/development/diaries.rb

日記のデータを作成していきます。このようなデータをidを変えて20個作成しました。

Diary.seed do |s|
  s.id = 1
  s.feeling = '😆'
  s.body = '⛱🐠'
  s.start_time  = Date.yesterday
  s.user_id = 1
end

ユーザーのデータを作成します。id、nickname、nameを変えて10個作成しました。

User.seed do |s|
  s.id = 1
  s.nickname = 'sayo'
  s.name = 'kimsayo'
  s.password  = "password"
end

そして開発環境のデータを作成しようとコマンドを叩くと、エラーに。。InvalidForeignKeyとなっているのですが、外部キーの設定が無効?

$ rails db:seed_fu RAILS_ENV=development

== Seed from /Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/db/fixtures/development/diaries.rb
 - Diary {:id=>1, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>1}
 - Diary {:id=>2, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>2}
 - Diary {:id=>3, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>3}
rails aborted!
ActiveRecord::InvalidForeignKey: Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`emoji_diary_development`.`diaries`, CONSTRAINT `fk_rails_f03fd03c63` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`))
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/rails:5:in `<top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:10:in `block in <top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `tap'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `<top (required)>'

Caused by:
Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails (`emoji_diary_development`.`diaries`, CONSTRAINT `fk_rails_f03fd03c63` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`))
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/rails:5:in `<top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:10:in `block in <top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `tap'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `<top (required)>'
Tasks: TOP => db:seed_fu
(See full trace by running task with --trace)

日記のデータを作るときに失敗しているのかな?と思ったので、user_idの指定の仕方を少し変えて再度試してみました。

Diary.seed do |s|
  s.id = 20
  s.feeling = '😆'
  s.body = '⛱🐠'
  s.start_time  = Date.today
  s.user_id = User.find(10)
end

またエラーです。NotNullViolationuser_idがnullになってしまっているらしい。。よくみてみるとuserのデータが全て入ってしまっています。これがエラーになる原因ですね。

$ rails db:seed_fu RAILS_ENV=development

== Seed from /Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/db/fixtures/development/diaries.rb
 - Diary {:id=>1, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>#<User id: 1, nickname: "sayo", name: "kimura34", crypted_password: "$2a$10$uIOXd191ACl0YkrVBwDvweTWj7T8XFkm4IpvMkkzGvb...", salt: "xkBkgsz_i9KxjRjyG2-X", created_at: "2021-05-22 17:06:12.899598000 +0900", updated_at: "2021-05-22 17:06:12.899598000 +0900">}
rails aborted!
ActiveRecord::NotNullViolation: Mysql2::Error: Field 'user_id' doesn't have a default value
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/rails:5:in `<top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:10:in `block in <top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `tap'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `<top (required)>'

Caused by:
Mysql2::Error: Field 'user_id' doesn't have a default value
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/rails:5:in `<top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:10:in `block in <top (required)>'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `tap'
/Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/bin/spring:7:in `<top (required)>'
Tasks: TOP => db:seed_fu
(See full trace by running task with --trace)

調べてみると、Userのデータが入る前に、DiaryがUserを参照しようとしてしまっているからみたいです。なのでシードデータの順番を制御することで解決するようです。seedのファイル名を下記のようにしました。

db/fixtures/development/01_users.rb
db/fixtures/development/02_diaries.rb

データを作成することができました。

$ rails db:seed_fu RAILS_ENV=development

== Seed from /Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/db/fixtures/development/01_users.rb
 - User {:id=>1, :nickname=>"sayo", :name=>"kimsayo", :password=>"password"}
 - User {:id=>2, :nickname=>"eri", :name=>"eri1112", :password=>"password"}
 - User {:id=>3, :nickname=>"yuka", :name=>"yuka911", :password=>"password"}
 - User {:id=>4, :nickname=>"ayaka", :name=>"110aya", :password=>"password"}
 - User {:id=>5, :nickname=>"asa", :name=>"asako", :password=>"password"}
 - User {:id=>6, :nickname=>"yuki", :name=>"bu8yuki", :password=>"password"}
 - User {:id=>7, :nickname=>"rina", :name=>"rina93", :password=>"password"}
 - User {:id=>8, :nickname=>"yuna", :name=>"yunana", :password=>"password"}
 - User {:id=>9, :nickname=>"nami", :name=>"namihe", :password=>"password"}
 - User {:id=>10, :nickname=>"mari", :name=>"maririn", :password=>"password"}

== Seed from /Users/SAYO/workspace/portfolio/emoji_diary/emoji_diary/db/fixtures/development/02_diaries.rb
 - Diary {:id=>1, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>1}
 - Diary {:id=>2, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>2}
 - Diary {:id=>3, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>3}
 - Diary {:id=>4, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>4}
 - Diary {:id=>5, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>5}
 - Diary {:id=>6, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>6}
 - Diary {:id=>7, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>7}
 - Diary {:id=>8, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>8}
 - Diary {:id=>9, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>9}
 - Diary {:id=>10, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Tue, 01 Jun 2021, :user_id=>10}
 - Diary {:id=>11, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>1}
 - Diary {:id=>12, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>2}
 - Diary {:id=>13, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>3}
 - Diary {:id=>14, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>4}
 - Diary {:id=>15, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>5}
 - Diary {:id=>16, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>6}
 - Diary {:id=>17, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>7}
 - Diary {:id=>18, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>8}
 - Diary {:id=>19, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>9}
 - Diary {:id=>20, :feeling=>"😆", :body=>"⛱🐠", :start_time=>Wed, 02 Jun 2021, :user_id=>10}

作成されたユーザーの情報に問題がありました。user_idが1と2のユーザーのpasswordのデータはちゃんと入っているのですが、user_idが3以降のユーザーのパスワードがnilになっていました。

irb(main):001:0> User.all
  User Load (51.0ms)  SELECT `users`.* FROM `users` /* loading for inspect */ LIMIT 11
=> #<ActiveRecord::Relation [#<User id: 1, nickname: "sayo", name: "kimsayo", crypted_password: "$2a$10$uIOXd191ACl0YkrVBwDvweTWj7T8XFkm4IpvMkkzGvb...", salt: "xkBkgsz_i9KxjRjyG2-X", created_at: "2021-05-22 17:06:12.899598000 +0900", updated_at: "2021-06-02 17:56:01.179817000 +0900">, 
#<User id: 2, nickname: "eri", name: "eri1112", crypted_password: "$2a$10$ebAXC5bqM0y8ZA9F/PIuF.2C6n5dSCbG6WUaMduqGQc...", salt: "SbmP96di6H6L9u8n7hyD", created_at: "2021-05-22 17:15:10.416046000 +0900", updated_at: "2021-05-22 17:15:10.416046000 +0900">, 
#<User id: 3, nickname: "yuka", name: "yuka911", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.234058000 +0900", updated_at: "2021-06-02 17:56:01.234058000 +0900">, 
#<User id: 4, nickname: "ayaka", name: "110aya", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.241600000 +0900", updated_at: "2021-06-02 17:56:01.241600000 +0900">, 
#<User id: 5, nickname: "asa", name: "asako", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.245346000 +0900", updated_at: "2021-06-02 17:56:01.245346000 +0900">, 
#<User id: 6, nickname: "yuki", name: "bu8yuki", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.249030000 +0900", updated_at: "2021-06-02 17:56:01.249030000 +0900">, 
#<User id: 7, nickname: "rina", name: "rina93", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.255090000 +0900", updated_at: "2021-06-02 17:56:01.255090000 +0900">, 
#<User id: 8, nickname: "yuna", name: "yunana", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.261832000 +0900", updated_at: "2021-06-02 17:56:01.261832000 +0900">, 
#<User id: 9, nickname: "nami", name: "namihe", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.264915000 +0900", updated_at: "2021-06-02 17:56:01.264915000 +0900">, 
#<User id: 10, nickname: "mari", name: "maririn", crypted_password: nil, salt: nil, created_at: "2021-06-02 17:56:01.270509000 +0900", updated_at: "2021-06-02 17:56:01.270509000 +0900">]>

seedファイルの書き方を今一度確認してみます。

User.seed do |s|
  s.id = 1
  s.nickname = 'sayo'
  s.name = 'kimsayo'
  s.password  = "password"
end
User.seed do |s|
  s.id = 2
  s.nickname = 'eri'
  s.name = 'eri1112'
  s.password  = "password"
end
User.seed do |s|
  s.id = 3
  s.nickname = 'yuka'
  s.name = 'yuka911'
  s.password  = "password"
end
User.seed do |s|
  s.id = 4
  s.nickname = 'ayaka'
  s.name = '110aya'
  s.password  = "password"
end
User.seed do |s|
  s.id = 5
  s.nickname = 'asa'
  s.name = 'asako'
  s.password  = "password"
end

passwordとプラスでpassword_cofirmaitonを追加してみようと思います。

User.seed do |s|
  s.id = 1
  s.nickname = 'sayo'
  s.name = 'kimsayo'
  s.password  = "password"
  s.password_confirmation = "password"
end
User.seed do |s|
  s.id = 2
  s.nickname = 'eri'
  s.name = 'eri1112'
  s.password  = "password"
  s.password_confirmation = "password"
end
User.seed do |s|
  s.id = 3
  s.nickname = 'yuka'
  s.name = 'yuka911'
  s.password  = "password"
  s.password_confirmation = "password"
end
User.seed do |s|
  s.id = 4
  s.nickname = 'ayaka'
  s.name = '110aya'
  s.password  = "password"
  s.password_confirmation = "password"
end
User.seed do |s|
  s.id = 5
  s.nickname = 'asa'
  s.name = 'asako'
  s.password  = "password"
  s.password_confirmation = "password"
end

rails consoleで調べてみます。

irb(main):001:0> User.all
  User Load (6.9ms)  SELECT `users`.* FROM `users` /* loading for inspect */ LIMIT 11
=> #<ActiveRecord::Relation [#<User id: 1, nickname: "sayo", name: "kimsayo", crypted_password: "password", salt: "password", created_at: "2021-05-22 17:06:12.899598000 +0900", updated_at: "2021-06-05 11:00:21.640283000 +0900">, 
#<User id: 2, nickname: "eri", name: "eri1112", crypted_password: "password", salt: "password", created_at: "2021-05-22 17:15:10.416046000 +0900", updated_at: "2021-06-05 11:00:21.654480000 +0900">, 
#<User id: 3, nickname: "yuka", name: "yuka911", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.234058000 +0900", updated_at: "2021-06-05 11:00:21.659504000 +0900">, 
#<User id: 4, nickname: "ayaka", name: "110aya", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.241600000 +0900", updated_at: "2021-06-05 11:00:21.662597000 +0900">, 
#<User id: 5, nickname: "asa", name: "asako", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.245346000 +0900", updated_at: "2021-06-05 11:00:21.665946000 +0900">, 
#<User id: 6, nickname: "yuki", name: "bu8yuki", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.249030000 +0900", updated_at: "2021-06-05 11:00:21.670000000 +0900">, 
#<User id: 7, nickname: "rina", name: "rina93", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.255090000 +0900", updated_at: "2021-06-05 11:00:21.673932000 +0900">, 
#<User id: 8, nickname: "yuna", name: "yunana", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.261832000 +0900", updated_at: "2021-06-05 11:00:21.678020000 +0900">, 
#<User id: 9, nickname: "nami", name: "namihe", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.264915000 +0900", updated_at: "2021-06-05 11:00:21.687091000 +0900">, 
#<User id: 10, nickname: "mari", name: "maririn", crypted_password: "password", salt: "password", created_at: "2021-06-02 17:56:01.270509000 +0900", updated_at: "2021-06-05 11:00:21.692096000 +0900">, ...]>

passwordは入っているように見えるのですが、全然ログインができません。。暗号化されていないからかな?と思ったので、パスワードの書き方を少し変えてみました。

参考 : https://qiita.com/reflet/items/eeced34f9c5c2a9fbaf6#暗号化そのものを行う関数

User.seed(
  :id,
  { id: 1, nickname: 'sayo', name: 'kimsayo', crypted_password: User.encrypt('password') },
  { id: 2, nickname: 'eri', name: 'eri1112', crypted_password: User.encrypt('password') },
  { id: 3, nickname: 'yuka', name: 'yuka911', crypted_password: User.encrypt('password') },
  { id: 4, nickname: 'miki', name: 'mickey', crypted_password: User.encrypt('password') },
  { id: 5, nickname: 'yuki', name: 'yuki8', crypted_password: User.encrypt('password') },
  { id: 6, nickname: 'ayaka', name: 'ayaka110', crypted_password: User.encrypt('password') },
  { id: 7, nickname: 'asa', name: 'asako', crypted_password: User.encrypt('password') },
  { id: 8, nickname: 'mari', name: 'mari7', crypted_password: User.encrypt('password') },
  { id: 9, nickname: 'yuna', name: 'yuna61', crypted_password: User.encrypt('password') },
  { id: 10, nickname: 'hina', name: 'hina4', crypted_password: User.encrypt('password') },
)

rails consoleで確かめてみるとsaltは未だ入っていなかったのですが、ログインできる情報は入っているのでOKです。

irb(main):001:0> User.all
  User Load (2.4ms)  SELECT `users`.* FROM `users` /* loading for inspect */ LIMIT 11
=> #<ActiveRecord::Relation [#<User id: 1, nickname: "sayo", name: "kimsayo", crypted_password: "$2a$10$xIWJ0vGGQ3TKMrFo52XNj.4an2CEobjzH6nA4crF/Sf...", salt: nil, created_at: "2021-06-05 12:16:43.581614000 +0900", updated_at: "2021-06-05 12:16:43.581614000 +0900">, 
#<User id: 2, nickname: "eri", name: "eri1112", crypted_password: "$2a$10$1Ojfr/S1IddywFPlkk9oNueWv81/LUA7z8Kf0ZWscu9...", salt: nil, created_at: "2021-06-05 12:16:43.587105000 +0900", updated_at: "2021-06-05 12:16:43.587105000 +0900">, 
#<User id: 3, nickname: "yuka", name: "yuka911", crypted_password: "$2a$10$uJtj9DG4283XqTOUObhMVOy3ee2t0dR.Cab/mUoRQLv...", salt: nil, created_at: "2021-06-05 12:16:43.592558000 +0900", updated_at: "2021-06-05 12:16:43.592558000 +0900">, 
#<User id: 4, nickname: "miki", name: "mickey", crypted_password: "$2a$10$p.aV4X8F6Xmn/RG/0wL5hO1cw.6rgs2qEbcU7v6EQSk...", salt: nil, created_at: "2021-06-05 12:16:43.595620000 +0900", updated_at: "2021-06-05 12:16:43.595620000 +0900">, 
#<User id: 5, nickname: "yuki", name: "yuki8", crypted_password: "$2a$10$MijtD1ZqwjdCGTyLuTuB7efHQFTBndffBhKUHsnKDPu...", salt: nil, created_at: "2021-06-05 12:16:43.598516000 +0900", updated_at: "2021-06-05 12:16:43.598516000 +0900">, 
#<User id: 6, nickname: "ayaka", name: "ayaka110", crypted_password: "$2a$10$1Pe2Uj.7DURX4HS11tL9.uUK3UZ7IGxWn.pSO47A5OZ...", salt: nil, created_at: "2021-06-05 12:16:43.601421000 +0900", updated_at: "2021-06-05 12:16:43.601421000 +0900">, 
#<User id: 7, nickname: "asa", name: "asako", crypted_password: "$2a$10$M/nYjlWnvo6ur7uhLVV4g.9uFJgqtII0GLK5l.UzS2a...", salt: nil, created_at: "2021-06-05 12:16:43.604262000 +0900", updated_at: "2021-06-05 12:16:43.604262000 +0900">, 
#<User id: 8, nickname: "mari", name: "mari7", crypted_password: "$2a$10$qIkdzXxvvAXtbsxPoRQgUO346iEwLX.Ga3s5pRB/Lyz...", salt: nil, created_at: "2021-06-05 12:16:43.606981000 +0900", updated_at: "2021-06-05 12:16:43.606981000 +0900">, 
#<User id: 9, nickname: "yuna", name: "yuna61", crypted_password: "$2a$10$5KTdmiWhHQaoFGh4nCkF1OW5ctaj5meqV1osK9UONPk...", salt: nil, created_at: "2021-06-05 12:16:43.610756000 +0900", updated_at: "2021-06-05 12:16:43.610756000 +0900">, 
#<User id: 10, nickname: "hina", name: "hina4", crypted_password: "$2a$10$.QoTsvb0tJSH7dQ5ZNBSOeqnEqCUclTt0qd3OviLNXq...", salt: nil, created_at: "2021-06-05 12:16:43.614056000 +0900", updated_at: "2021-06-05 12:16:43.614056000 +0900">, ...]>