Skip to content

RegularEvent#organizersがhas_manyの関連メソッドを上書きしている #9640

@yokomaru

Description

@yokomaru

概要

  • RegularEventにてhas_many :organizersを定義しているが、同名のdef organizersが定義されているため、ActiveRecordの関連メソッドを上書きしている状態になっている
    • 意図的に上書きをしているかどうかは当時のコミットメッセージから読み取れず
  • 現状、regular_event.organizersOrganizerではなくUserを返している
class RegularEvent < ApplicationRecord # rubocop:disable Metrics/ClassLength
  has_many :organizers, dependent: :destroy
  has_many :users, through: :organizers


  def organizers
    users.preload(avatar_attachment: :blob).order('organizers.created_at')
  end

end

発行されるSQLの違い

# メソッドの上書きあり(`organizers`と書くと`User`が引っ張られる)
bootcamp(dev):002> RegularEvent.last.organizers.to_sql
  RegularEvent Load (1.0ms)  SELECT "regular_events".* FROM "regular_events" 
ORDER BY "regular_events"."id" DESC LIMIT 1 /*application='Bootcamp'*/
=> "SELECT "users".* FROM "users" INNER JOIN "organizers" ON "users"."id" = \"organizers\".\"user_id\" 
WHERE \"organizers\".\"regular_event_id\" = 1004488906 ORDER BY organizers.created_at"
# メソッドの上書きなし(`organizers`と書くと`Organizer`が引っ張られる)
bootcamp(dev):004> RegularEvent.last.organizers.to_sql
  RegularEvent Load (0.5ms)  SELECT "regular_events".* FROM "regular_events" 
ORDER BY "regular_events"."id" DESC LIMIT 1 /*application='Bootcamp'*/
=> "SELECT \"organizers\".* FROM \"organizers\" WHERE \"organizers\".\"regular_event_id\" = 1004488906"

問題点

  • メソッド名と実体が一致しておらず読み手が混乱しやすい(organizersなのにUserが返る)
  • regular_event.organizers.destroy_allなどを書いた場合、意図せずUserが削除されてしまう可能性がある
  • また、現状regular_event.usersorganizersになっているUserを持って来れるが、別のUserとの関連モデルであるParticipation(参加者)もあるため、usersだとどちらを参照しているのかわかりづらい

期待される振る舞い

  • regular_event.organizersOrganizerを返すようにしたい
  • 主催者ユーザー一覧が必要なら別名にする(例:organizer_users
    • 別名のhas_manyアソシエーションを作り必要な情報を引っ張って来れるようにする
    • scopeで定義でも良い?
  • 不要になったコードは削除する

対応内容

  • OrganizerモデルをRegularEventOrganizerにリネーム
  • organizersテーブルをregular_event_organizersに変更
  • 関連(has_many / through)を修正
  • scopeorder句などクエリ内のテーブル参照を修正
  • organizersメソッド内の参照テーブルを修正(互換性のためメソッドは維持)
  • Fixture / seed の名称変更
  • 複合インデックスを使用できるため、不要なインデックス(user_id単体)を削除

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

ステージング確認中

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions