3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ActiveRecord】inverse_of, class_nameオプション を使って、自然な文脈で読めるコードを書く

Last updated at Posted at 2025-11-30

前提

サンプルコード等、Ruby on Railsを前提にしてます

概要

inverse_of、class_nameの説明をします。
どちらもActiveRecordの関連付けに用いるオプションです。

inverse_ofとは

Rails に双方向関連を明示し、同一オブジェクトを共有したり、バリデーションを適切に行うための設定です。

class_nameとは

関連名と実際のクラス名を明示的に指定するためのオプションです。
普段は暗黙的にRailsが判断してくれています。

どんな時に使うか

まず、Rails でモデルの関連を素直に設定すると、よくこうなります。


class User < ApplicationRecord
  has_one :user_profile, dependent: :destroy
end

class UserProfile < ApplicationRecord
  belongs_to :user
end

# bad
user.user_profile.nickname

user.user_profile というのが、なんとも言えず読みにくい。

そのコードを


# good
user.profile.nickname

こういう自然と読めるコードを書きたいときに、

  • 「関連名とクラス名を対応させる」 → class_name
  • 「反対側の関連がどれかを伝える」 → inverse_of

をセットで使うと便利です。

設定方法

公式のソース

サンプルコード

先ほどのUserの例の延長で書きます。


class User < ApplicationRecord
  has_one :profile,
          dependent: :destroy,
          class_name: 'UserProfile', # ← 関連名とクラス名が異なるので、明示的に指定する
          inverse_of: :user # ← UserProfile 側の :user と対応
end

class UserProfile < ApplicationRecord
  belongs_to :user,
             inverse_of: :profile # ← User 側の :profile と対応
end

これによって、先ほどもあげた


# good!
user.profile.nickname

のような、シンプルで自然なコードを記述することができます。
また、Rails的にも双方向関連を扱えるようになります。

他の例

個人的にやってみた例を挙げます。

変更前


# 部署と従業員で1対多の関係

class Department < ApplicationRecord
    has_many :employees, dependent: :destroy,
    
end

class Employee < ApplicationRecord
    belongs_to :department
end

# 参照の仕方
department.employees

これでもいいんですが、個人的には

  • 全ての従業員が含まれうる命名 → employees
  • 特定の所属に属する従業員の命名 → ?

この二つの違いがパッと見てわかるようにしたかったというのがあり、別名をつけました。

変更後


# 部署と従業員で1対多の関係

class Department < ApplicationRecord
    has_many :members, # ← ここを変更
             dependent: :destroy,
             class_name: 'Employee',
             inverse_of: :department
    
end

class Employee < ApplicationRecord
    belongs_to :department,
               inverse_of: :members
end

# 特定の所属のメンバー
department.members

departmentから見た時のみ、「employee」ではなく「member」と呼ぶことにしています。
そうすることで

  • 全ての従業員が含まれうる命名 → employees
  • 特定の所属に属する従業員の命名 → ?

この区別をつけやすくしました。

まとめ

チーム内で毎週2種類(This Week In Rails と Railsguides)の輪読会をしていて、双方向関連付について最近ガイドを読んだので、業務の中でいろいろと試してみています。

has_oneの関連テーブルなどで使える場面は多いのでよければ試してみて欲しいです。

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?