Download - ActiveRecordでレガシーテーブルにつないだ話
![Page 1: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/1.jpg)
ActiveRecordでレガシーテーブルに繋いだらスタンド攻撃を受けた話
@ryonext
![Page 2: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/2.jpg)
• タイトルは釣りです
![Page 3: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/3.jpg)
自己紹介
• Twitter ID @ryonext
• ハンターランク151のモンハン厨です
• 新横浜にあるOA機器メーカーでビデオ会議のシステム作ってます
• RailsでAPIとかテスト書いたりとか
![Page 4: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/4.jpg)
ActiveRecordは便利ですね 1 class CreateUsers < ActiveRecord::Migration! 2 def change! 3 create_table :users do |t|! 4 t.string :name! 5 t.integer :age! 6 t.string :type! 7 ! 8 t.timestamps! 9 end!10 end!11 end
![Page 5: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/5.jpg)
14 ActiveRecord::Schema.define(version: 20131116064854) do!15 !16 create_table "users", force: true do |t|!17 t.string "name"!18 t.integer "age"!19 t.string "type"!20 t.datetime "created_at"!21 t.datetime "updated_at"!22 end!23 !24 end
![Page 6: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/6.jpg)
mysql> desc users; +------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(255) | YES | | NULL | | | age | int(11) | YES | | NULL | | | type | varchar(255) | YES | | NULL | | | created_at | datetime | YES | | NULL | | | updated_at | datetime | YES | | NULL | | +------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
![Page 7: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/7.jpg)
ActiveRecordの規約に沿っていないテーブル
mysql> desc legacy_user; +-------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------------+--------------+------+-----+---------+-------+ | userID | int(11) | NO | PRI | 0 | | | name | varchar(255) | YES | | NULL | | | age | int(11) | YES | | NULL | | | someLegacyParams1 | varchar(255) | YES | | NULL | | | someLegacyParams2 | varchar(255) | YES | | NULL | | | someLegacyParams3 | varchar(255) | YES | | NULL | | +-------------------+--------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
+--------------------+ | Tables_in_legacydb | +--------------------+ | legacy_user | +--------------------+
![Page 8: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/8.jpg)
こんな感じでつなげます
14 legacy:!15 adapter: mysql2!16 database: legacyDB!17 username: root!18 password:!19 pool: 5!20 timeout: 5000
config/database.yml
1 class LegacyUser < ActiveRecord::Base!2 establish_connection(:legacy)!3 self.table_name = "legacy_user"!4 end
app/models/legacy_user.rb
![Page 9: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/9.jpg)
ただし
![Page 10: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/10.jpg)
こんなテーブルが合ったとする
mysql> desc hyper_legacy_tbl; +-----------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+---------+------+-----+---------+-------+ | legacy_id | int(11) | NO | PRI | 0 | | | id | int(11) | YES | | NULL | | +-----------+---------+------+-----+---------+-------+
2 rows in set (0.01 sec)
‘id’というカラムをもつが、主キーではなく普通のカラム
![Page 11: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/11.jpg)
つないでみる
1 class HyperLegacyTbl < ActiveRecord::Base!2 establish_connection(:legacy)!3 self.table_name = "hyper_legacy_tbl"!4 end
![Page 12: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/12.jpg)
繋がったようにみえる
[5] pry(main)> h = HyperLegacyTbl.new => #<HyperLegacyTbl legacy_id: 0, id: nil>
![Page 13: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/13.jpg)
‘id’を更新してみる
[6] pry(main)> h.id = 100 => 100 [7] pry(main)> h.save
![Page 14: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/14.jpg)
ファッ!?
(0.2ms) BEGIN SQL (0.3ms) INSERT INTO `hyper_legacy_tbl` (`legacy_id`) VALUES (100) (0.1ms) COMMIT => true [8] pry(main)> h => #<HyperLegacyTbl legacy_id: 100, id: nil>
![Page 15: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/15.jpg)
![Page 16: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/16.jpg)
なぜなのか
• “#id”によるアクセスはprimary_keyへのアクセスになっている
• “id”という名前のパラメータへのアクセスではない
![Page 17: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/17.jpg)
対処:既存レコードの場合
[36] pry(main)> h = HyperLegacyTbl.first HyperLegacyTbl Load (0.4ms) SELECT `hyper_legacy_tbl`.* FROM `hyper_legacy_tbl` ORDER BY `hyper_legacy_tbl`.`legacy_id` ASC LIMIT 1 => #<HyperLegacyTbl legacy_id: 100, id: 200> [37] pry(main)> h.id => 100 [38] pry(main)> h.legacy_id => 100 [39] pry(main)> h.attributes["id"] => 200
取得には“#attributes[“id”]”を使う
![Page 18: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/18.jpg)
対処:既存レコードの場合
[45] pry(main)> h.update_column("id", 1000) SQL (0.3ms) UPDATE `hyper_legacy_tbl` SET `hyper_legacy_tbl`.`id` = 1000 WHERE `hyper_legacy_tbl`.`legacy_id` = 100 => true
更新には“update_column”を使う
[46] pry(main)> h.update_column("id", 3000) SQL (0.3ms) UPDATE `hyper_legacy_tbl` SET `hyper_legacy_tbl`.`id` = 3000 WHERE `hyper_legacy_tbl`.`legacy_id` = 1000 => false
ただし、データを取りなおさないで2連続でやると失敗する
![Page 19: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/19.jpg)
新規の場合
• Insertのときはupdate_columnが使えないので違う方法が必要?(未調査)
• 直接SQLを発行してしまえば
• それもうActiveRecordつかわなくていいよね説
![Page 20: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/20.jpg)
どこで定義されているのか• #id
• lib/active_record/attribute_methods/primary_key.rb
• #define_method_attribute(attr_name)
• #id=
• lib/active_record/attribute_methods/write.rb
• #write_attribute(attr_name, value)
![Page 21: ActiveRecordでレガシーテーブルにつないだ話](https://reader034.vdocuments.pub/reader034/viewer/2022051816/5463cd21b4af9f3f3f8b46a9/html5/thumbnails/21.jpg)
まとめ
• ‘id’っていう名前を持つテーブルにActiveRecordでつなぐときは注意しましょう