0
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?

【Rails】inverse_of

Posted at

はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。
Rails の関連(has_many / belongs_to / has_one など)には inverse_of というオプションがあります。
これは「逆方向の関連が何であるか」を Rails に伝えるものです。

Rails は通常、関連を自動で推測してくれるのですが、複雑な関連やスコープ付き関連では推測できない場合があるので、明示的に書く必要が出てきます。


なぜ必要なのか?

例: has_many と belongs_to

class Author < ApplicationRecord
  has_many :books
end

class Book < ApplicationRecord
  belongs_to :writer, class_name: "Author", foreign_key: "author_id"
end

inverse_of を書いていないと、関連オブジェクトを呼ぶたびに新しいインスタンスが生成されることがあり、
「同じはずの author が別物」になってしまうケースが出ます。
これは特に メモリ上でのオブジェクト同一性を大事にする処理(キャッシュやバリデーション) で不具合の原因になります。

author = Author.new(name: "Taro")
book = author.books.build(title: "My Book")

book.writer.equal?(author) # => false の場合がある!

書き方のポイント

自動推測されない場合は必ず書く

  • スコープ付き関連
  • class_name / foreign_key を指定した関連
  • 名前が変わっている関連
class User < ApplicationRecord
  has_many :authored_articles,
           class_name: "Article",
           foreign_key: :author_id,
           inverse_of: :author
end

class Article < ApplicationRecord
  belongs_to :author,
             class_name: "User",
             inverse_of: :authored_articles
end

has_many :through の場合は効かない

through を経由した関連には inverse_of は使えません。

polymorphic 関連でも効かない

belongs_to :commentable, polymorphic: true のような関連では逆方向が特定できないため使えません。


まとめ

  • inverse_of は関連の逆方向を Rails に教えるオプション
  • 通常は自動推測されるので書かなくて良いが、以下の場合は書くようにする
    • スコープ付き関連
    • class_name / foreign_key をカスタムした関連
  • throughpolymorphic 関連には使えない

参考資料

0
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
0
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?