今回は外部キーがnilでもエラーが出ない方法について解説します。
infomationテーブル
id |
talent_name |
age |
user_id |
---|---|---|---|
1 | 山田太郎 | 20 | nil |
2 | 山田花子 | 20 | nil |
usersテーブル
id |
login_name |
---|---|
1 | nick |
2 | tom |
今回はこの2つのテーブルを使います。usersテーブルとinfomationテーブルはアソシエーションを組んでいます。
usersテーブルは親で、infomationテーブルは子です。
※マーク今回infomationテーブルはどんな情報が追加されてもuser_idカラムは'nil'とします
その状態でスクレイピングをしたらこのようになります。
Running via Spring preloader in process 5268
Loading development environment (Rails 5.2.4.4)
[1] pry(main)> Scraping.get_infomation
D, [2020-11-09T06:30:25.470701 #5268] DEBUG -- : (0.3ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
D, [2020-11-09T06:30:25.489471 #5268] DEBUG -- : Infomation Load (1.5ms) SELECT `infomations`.* FROM `infomations` WHERE `infomations`.`name` = '波瑠' ORDER BY `infomations`.`id` ASC LIMIT 1
D, [2020-11-09T06:30:25.503981 #5268] DEBUG -- : (0.1ms) BEGIN
D, [2020-11-09T06:30:25.524340 #5268] DEBUG -- : (0.1ms) ROLLBACK
Return value is: nil
[24, 33] in /home/ec2-user/environment/filebook/app/models/scraping.rb
24: names = aaas.at('h1').inner_text if aaas.at('h1')
25: image_urls = personal_page.at('.main_image img').get_attribute('src') if personal_page.at('.main_image img')
26: infomation = Infomation.where(name: names).first_or_initialize
27: infomation.age = ages
28: infomation.image_url = image_urls
29: infomation.save
30:
31: byebug
=> 32: end
33: end
(byebug) infomation
#<Infomation id: nil, age: 29, name: "波瑠", image_url: "https://images.talent-dictionary.com/uploads/image...", created_at: nil, updated_at: nil>
(byebug)
本当はuser_idカラムがあります。user_id: nil ごめん
途中でrollbackされinfomationテーブルにはidがnil,created_atやupdated_atもnilとなっており保存ができないことがわかります。
そこで今回
user_idがnilでも保存できる方法を解説します。
まずは小要素のモデルを開いてください。
infomation.rb
class Infomation < ApplicationRecord
belongs_to: user
end
このようにアソシエーションを組んでいると思いますがその横にoptional: trueをつけてください。
infomation.rb
class Infomation < ApplicationRecord
belongs_to: user,optional: true
end
そうすると
Running via Spring preloader in process 6358
Loading development environment (Rails 5.2.4.4)
[1] pry(main)> Scraping.get_infomation
D, [2020-11-09T06:45:18.429070 #6358] DEBUG -- : (0.4ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
D, [2020-11-09T06:45:18.434125 #6358] DEBUG -- : Infomation Load (0.2ms) SELECT `infomations`.* FROM `infomations` WHERE `infomations`.`name` = '美山加恋' ORDER BY `infomations`.`id` ASC LIMIT 1
D, [2020-11-09T06:45:18.440170 #6358] DEBUG -- : (0.1ms) BEGIN
D, [2020-11-09T06:45:18.442031 #6358] DEBUG -- : Infomation Create (0.2ms) INSERT INTO `infomations` (`age`, `name`, `image_url`, `created_at`, `updated_at`) VALUES (23, '美山加恋', 'https://images.talent-dictionary.com/uploads/images/tldb/086a19d1703dda4390ae74328861c5c858939acb.jpg', '2020-11-09 06:45:18', '2020-11-09 06:45:18')
D, [2020-11-09T06:45:18.444995 #6358] DEBUG -- : (2.3ms) COMMIT
Return value is: nil
[23, 32] in /home/ec2-user/environment/filebook/app/models/scraping.rb
23: ages = aaas.at('.age').inner_text.delete('歳').to_i if aaas.at('.age')
24: names = aaas.at('h1').inner_text if aaas.at('h1')
25: image_urls = personal_page.at('.main_image img').get_attribute('src') if personal_page.at('.main_image img')
26: infomation = Infomation.where(name: names).first_or_initialize
27: infomation.age = ages
28: infomation.image_url = image_urls
29: infomation.save
30: byebug
=> 31: end
32: end
(byebug)
ちゃんとコミットされて保存されてますね!!!!!!
ちなみにoptional: trueとは外部キーのnilを許可すると言うことです。