はじめに
こんばんは。
金曜日の夜ですね。明日が休みだと思うと朝起きなくていいからでしょうか。心なしか色々捗る気がします。
でもそろそろ眠たいので1日いちQiitaを残して夢の国に旅立とうと思います。
この記事で書くこと
Active Recordのアソシエーション(公式railsguidesへのリンクを貼っておきます)の
has_and_belongs_to_many
の実装コードを読んでみて気づいたことをつらつらと書く。
背景
多対多の関連付けを表現するとき has_and_belongs_to_many
か has_many :through
どちらを選択しますかという問いに対し自分は1年前Railsを習い始めた頃チームの人に教わりながら has_and_belongs_to_many
を選択し実装しました。
ですから、実体の仲介テーブルを持ち、そこに2つの多対多の関係をもつモデルのidをセットで保存して関連を表現していたんですね。
でも、今直近で多対多の関連をもつことになりそうなモデルがあり、 has_and_belongs_to_many
使ってるのなぜなの? has_many :through
を使わない理由があるってこと?とPRで質問された時に自分は明確に理由を応えることができず、それがきっかけで、この2つの方法についてしっかり考えようと思いました。
※世の中(google先生の用意してる世界)で has_and_belongs_many
やめよう! という意見が多いのも目にしました。
が、ここでは特に世の皆さんがおっしゃってるような内容をそう思うということを書くのではなく、あくまでコードをよんで自分が理解できたこと、できないこと、その上での2つの違いについてまとめていけたらいいなと思っています。
よし、よむ。
このメソッドに関して読んだ結果という感想
-
モデル名いつもどっちが複数だったっけとmigrateするとき思ってたいたけれどここをよんで理解。
https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb#L65 -
内部的には
has_many
を使用している。
https://github.com/rails/rails/blob/0af3dd4438047d8c5783dff1cfcf9c696b44bdff/activerecord/lib/active_record/associations.rb#L1720 -
leftとrightそれぞれで 他方へ
belongs_to
している
https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb#L59 -
内部的にClassをnewしている。そのnewされるクラスが関連を表現する中間モデル。
https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb#L14 -
macroがどこで定義されてるのか一瞬わからなかった。でも インスタンスメソッドですぐraiseしていたので、継承してる先で定義してるんだなと思ってもどったら
HasMany
にて発見できてよかった。
https://github.com/rails/rails/blob/b2eb1d1c55a59fee1e6c4cba7030d8ceb524267c/activerecord/lib/active_record/associations/builder/has_many.rb#L5 -
この一行は何だか凄くすっきりしていていいなぁと思った。自分もここ使ってみたらいいかもとおもえた時に使っていきたい。
https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/activerecord/lib/active_record/reflection.rb#L18 -
この一行何をやってるの? HasManyの関連をするためにreflectionをcreateするためにここでやる必要があるの?わからない。
https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb#L69
謎が残った。
今日は has_and_belongs_to_many
について駆け足でしかできませんでした。
「その1」とタイトルをつけた以上、 has_many :through
についてのコードも明日読みたいと思います。図とかかいて整理しようかな。。
では今週も平日お疲れ様でした。
おやすみなさい。良い夜を。
Happy coding!