月曜日までに考えておきます

ITネタとゲームネタ中心に興味のあること色々書きます。

さらにActiveRecord#idを調べて討死中

前回の記事 で @udzura さんからalias_attributeならどうか、というコメントを頂いたのでこちらも試してみました。

1. self.primary_key = :legacy_idを入れる場合

こんな感じで、:idを:sushiとして定義。

class LegacyUser < ActiveRecord::Base
  establish_connection(:legacy)
  self.table_name = "hyper_legacy_tbl"
  self.primary_key = :legacy_id
  alias_attribute :sushi, :id
end

結果、

[10] pry(main)> h = HyperLegacyTbl.first
  HyperLegacyTbl Load (0.3ms)  SELECT `hyper_legacy_tbl`.* FROM `hyper_legacy_tbl` ORDER BY `hyper_legacy_tbl`.`legacy_id` ASC LIMIT 1
=> #<HyperLegacyTbl legacy_id: 1, id: 100>
[11] pry(main)> h.sushi
=> 1
[12] pry(main)> h.id
=> 1
[13] pry(main)> h.attributes["id"]
=> 100

ailias_attributesの時点ですでにidはプライマリキーである"legacy_id"の方を向いている、ということ? 前回調べたとき、self.primary_key = :idなら"id"カラムの方を向いてくれたのにこっちだとだめなのかよ。

2. self.primary_key = :legacy_id がない場合

class HyperLegacyTbl < ActiveRecord::Base
  establish_connection(:legacy)
  self.table_name = "hyper_legacy_tbl"
  alias_attribute :sushi, :id
end
[1] pry(main)> h = HyperLegacyTbl.first
  HyperLegacyTbl Load (0.3ms)  SELECT `hyper_legacy_tbl`.* FROM `hyper_legacy_tbl` ORDER BY `hyper_legacy_tbl`.`legacy_id` ASC LIMIT 1
=> #<HyperLegacyTbl legacy_id: 1, id: 100>
[2] pry(main)> h.id
=> 1
[3] pry(main)> h.sushi
=> 1
[4] pry(main)> h.attributes["id"]
=> 100

ぐぬぬ

3. トリッキーなことしてみる

class HyperLegacyTbl < ActiveRecord::Base
  establish_connection(:legacy)
  self.table_name = "hyper_legacy_tbl"
  self.primary_key = :id
  alias_attribute :sushi, :id
  self.primary_key = :legacy_id
end

エイリアスするときの:idはカラムの"id"を見てるはず

結果!

[1] 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: 1, id: 100>
[2] pry(main)> h.sushi
=> 1
[3] pry(main)> h.id
=> 1
[4] pry(main)> h.attributes["id"]
=> 100

(´・ω・`)

4. self.primary_key = :id だけにしてみる

primary_keyを:idだけにする

class HyperLegacyTbl < ActiveRecord::Base
  establish_connection(:legacy)
  self.table_name = "hyper_legacy_tbl"
  self.primary_key = :id
  alias_attribute :sushi, :id
end
[1] pry(main)> h = HyperLegacyTbl.first
  HyperLegacyTbl Load (0.3ms)  SELECT `hyper_legacy_tbl`.* FROM `hyper_legacy_tbl` ORDER BY `hyper_legacy_tbl`.`id` ASC LIMIT 1
=> #<HyperLegacyTbl legacy_id: 1, id: 100>
[2] pry(main)> h.sushi
=> 100
[3] pry(main)> h.id
=> 100
[4] pry(main)> h.legacy_id
=> 1

こうなるけど〜

[5] pry(main)> h.sushi = 1000
=> 1000
[6] pry(main)> h.save
   (0.2ms)  BEGIN
  SQL (0.3ms)  UPDATE `hyper_legacy_tbl` SET `id` = 1000 WHERE `hyper_legacy_tbl`.`id` = 100
   (0.2ms)  COMMIT
=> true

update, deleteが危険な感じになるのは前回の記事と同じですね。(※idは重複する可能性があります)

おまけ?

primary_key=の動きでailias_attributeの動きが変わるのか?と思って以下の処理を動かしてみました。HyperLegacyTblの実装は上の4と同じです。

[2] pry(main)> h.sushi
=> 1000
[3] pry(main)> HyperLegacyTbl.primary_key = :legacy_id
=> :legacy_id
[4] pry(main)> h.sushi
=> 1000

後者の方の#sushiはprimary_keyが変わったから:legacy_idの値である"1"が返って来るんじゃないか、と思ったら違ったので予想外。 そして、

[6] pry(main)> h.id = 2000
=> 2000
[7] pry(main)> h.save
   (0.2ms)  BEGIN
  SQL (0.3ms)  UPDATE `hyper_legacy_tbl` SET `id` = 1000 WHERE `hyper_legacy_tbl`.`legacy_id` = 1000
   (0.2ms)  COMMIT
=> true
[8] pry(main)> HyperLegacyTbl.all
  HyperLegacyTbl Load (0.3ms)  SELECT `hyper_legacy_tbl`.* FROM `hyper_legacy_tbl`
=> [#<HyperLegacyTbl legacy_id: 1, id: 1000>]

なんか発行されているSQLがいろいろおかしい。入力した2000はどこへ行ってもうたんや・・・。

この後もインスタンスはこう。

[9] pry(main)> h
=> #<HyperLegacyTbl legacy_id: 2000, id: 1000>

DBは発行されているSQLに従っているので当然こうですね。

mysql> select * from hyper_legacy_tbl;
+-----------+------+
| legacy_id | id   |
+-----------+------+
|         1 | 1000 |
+-----------+------+
1 row in set (0.00 sec)

またポルナレフ状態になってきたwww