その他

【Rails】class_nameとsourceオプションで分かりやすいアソシエーション名をつけよう

今日はRailsで少し複雑なアソシエーションを組む方法について書いていこうと思います。アソシエーションを自在に組めるようになると、コードの見通しがすごくよくなるので自然と書けるようになりたいものです。

使用するサンプルアプリ

今回もユーザがイベントを開催でき、また参加できるアプリを例に書いていきます。ユーザは複数のイベントを開催でき、イベントは複数の参加するユーザを持てるので多対多の関係になります。そこで、中間テーブルとしてチケットテーブルを作っています。

アソシエーションを組んでみる

では実際にUserモデルにアソシエーションを定義していきます。

class User < ApplicationRecord
  has_many :events, foreign_key: "owner_id"
  has_many :tickets
  has_many :events, through: :tickets
end

多対多のアソシエーションの場合、has_many: (中間テーブル)とした上で、has_many :(多対多関連先のテーブル名)としてthroughオプションで中間テーブルを指定します。
この際、中間テーブルのアソシエーションを前に書かないとエラーになるので気をつけてください。

もぐくん
もぐくん
なんかエラーになったぞ
さかい
さかい
中間テーブルのアソシエーションの位置に気をつけて!

しかし、これではuser.eventsとしたときに、名前の衝突が起きていて、開催するイベントなのか参加するイベントなのか分かりません。そこで、分かりやすい名前にアソシエーション名を変更します。

has_many :created_events, class_name: "Event", foreign_key: "owner_id"
has_many :participating_events, through: :tickets, source: event

まず、開催するイベントのアソシエーションをcreated_eventsとしました。これで、user.created_eventsとたとき、開催するイベントを取得していることがひと目で分かります。ただし、関連名がモデル名ではなくなったため、どのモデルのものなのかをきちんと明示して上げる必要があります。そのときに使うオプションがclass_nameです。

1対多で関連先のモデル名を指定するオプションがclass_name

また、参加しているイベントのアソシエーションをparticipating_eventsとしました。これもuser.participating_eventsとしたとき、ユーザが開催しているイベントを取得していることが分かります。ここでも関連先のモデル名がRails側で分からないので、きちんと明示する必要があります。そのときに使うオプションがsourceです。先程のclass_nameと使い所は似てますが、こちらは多対多のときに使います。

多対多の関連先のモデル名を指定するオプションがsource

まとめ

このテクニックを使ってアソシエーションに分かりやすい名前をつけて、見通しのよいコードにしていきましょう。

ABOUT ME
酒井 駿
名古屋工業大学大学院卒業後、豊田合成(株)で品質管理を経験し、その後スタートアップ・マネーフォワードを経て、2024年11月に株式会社EGGHEAD創業。 製造業とエンジニアリング、両方の現場の知見を活かし、製造業における生成AIを活用した業務改善やシステム開発を支援します。