【Rails】has_many through について

最近、active recordをダラダラいじってるけど全然慣れない。。今回は少しでも理解を深めるために「has_many through」構文?のオプションを省略せずに書いてみたのでメモとして残して置く。

テーブル構造は、以下のようにrailsの規則どおりのもの。
users(id) <==> bank_user(user_id / bank_id) <==> banks(id)

最低限の書き方

class Bank < ApplicationRecord
  has_many :bank_users
  has_many :users, :through => :bank_users
end                                                                                                                                                                                                                
                                                                                                                                                                                                                   
class User < ApplicationRecord
  has_many :bank_users
  has_many :banks, :through => :bank_users
end                                                                                                                                                                                                                
                                                                                                                                                                                                                   
class BankUser < ApplicationRecord
  belongs_to :user
  belongs_to :bank
end

オプションもあえて書く

class Bank < ApplicationRecord
  has_many :bank_users, class_name: "BankUser", primary_key: "id", foreign_key: "bank_id"
  has_many :users, :through => :bank_users
end

class User < ApplicationRecord
  has_many :bank_users, class_name: "BankUser", primary_key: "id" , foreign_key: "user_id"
  has_many :banks, :through => :bank_users
end

class BankUser < ApplicationRecord
  belongs_to :user, class_name: "User", primary_key: "id" , foreign_key: "user_id"
  belongs_to :bank, class_name: "Bank", primary_key: "id" , foreign_key: "bank_id"
end

命名規則に沿っていると、class_name、primary_key、foreign_keyは省略できるみたい。

実行してみる

$ User.joins(:banks)
User Load (1.5ms)  SELECT  `users`.* FROM `users` INNER JOIN `bank_users` ON `bank_users`.`user_id` = `users`.`id` INNER JOIN `banks` ON `banks`.`id` = `bank_users`.`bank_id` LIMIT 11

$ Bank.joins(:users)
Bank Load (0.5ms)  SELECT  `banks`.* FROM `banks` INNER JOIN `bank_users` ON `bank_users`.`bank_id` = `banks`.`id` INNER JOIN `users` ON `users`.`id` = `bank_users`.`user_id` LIMIT 11

・has_manyの場合
class_name : 参照先のモデルクラス名
primary_key : 参照元(自分)の外部キー
foreign_key : 参照先の外部キー

・belongs_toの場合
class_name : 参照先のモデルクラス名
primary_key : 参照先の外部キー
foreign_key : 参照元の外部キー

動きみてると、とりあえずこの解釈で良いのかな。以上です。