LoginSignup
2
1

More than 5 years have passed since last update.

has_manyとbelongs_toにinverse_ofオプションが必要なケースを検証してみた

Last updated at Posted at 2019-03-31

has_manyとbelongs_toでinverse_ofオプションが必要なケースを検証してみました。
結論から書くとhas_manyinverse_ofが必要なケースは検証できましたがbelongs_toでの必要なケースが不明でした。

検証に使用したリポジトリ

has_manyでinverse_ofが必要なケース(ソース抜粋)

# app/models/blog.rb
has_many :articles, -> { order(id: :desc) }, dependent: :destroy, inverse_of: :blog
accepts_nested_attributes_for :articles, reject_if: :all_blank

#app/models/article.rb
validate ->(article) {
  if article.blog.title == article.title
    errors.add(:title, 'blogタイトルとarticleタイトルが同じではいけない')
  end
}

has_manyでinverse_ofが不要なケース(ソース抜粋)

# app/models/blog.rb
has_many :articles, dependent: :destroy
accepts_nested_attributes_for :articles, reject_if: :all_blank

# app/models/article.rb
# 必要なケースと同じソース

上記の結果から分かること

  • -> { order(id: :desc) }の有無でinverse_ofの必要性が決まりました。
  • -> { order(id: :desc) }がある状態でinverse_ofをつけないとvalidateの中のarticle.blogが参照できずnilになりました。(inverse_ofをつけると参照できました)

belolngs_toにinverse_ofが必要なケースを検証

(そもそも= simple_form_for(@article)のフォームから親のBlogを生成するケース自体、稀かもしれませんが…)

実際に試してみたブランチ

belongs_toでinverse_ofをつけた場合(ソース抜粋)

# app/models/blog.rb
validate ->(blog) {
  if blog.articles.map(&:title).include?(blog.title)
    errors.add(:title, 'blogタイトルとarticleタイトルが同じではいけない')
  end
}

# app/models/article.rb
belongs_to :blog, inverse_of: :articles
accepts_nested_attributes_for :blog

フォームで送信したはずのArticleのデータblog.articlesが参照できませんでした。(デバッグのためblog.articles.lengthと書いても0が返ります)

belongs_toinverse_ofを書けば保存前のblog.articlesが参照できると考えていましたが、実際にはそのような動きにはなりませんでした。

追記(2019年4月6日)

勉強会でご一緒した方にhas_many - belongs_toの関係でbelongs_toに設定したinverse_ofは現状サポートされていないとの情報を共有いただきました。
情報共有いただきまして感謝いたします!

下記はhttps://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations/belongs_to_association.rb#L111-L112からコメント抜粋

# NOTE - for now, we're only supporting inverse setting from belongs_to back onto
# has_one associations.

参考

2
1
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
2
1