Ruby on Rails

【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
sakai
東京在住の30歳。元々は車部品メーカーで働いていてましたが、プログラミングに興味を持ちスクールに通ってエンジニアになりました。 そこからベンチャー → メガベンチャー → 個人事業主になりました。 最近は生成 AI 関連の業務を中心にやっています。 ヒカルチャンネル(Youtube)とワンピースが大好きです!