LoginSignup
2
1

More than 3 years have passed since last update.

外部キーがnilでも保存できる方法

Posted at

今回は外部キーが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を許可すると言うことです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1