7
3

More than 3 years have passed since last update.

[Rails]親モデルから孫モデルを直接参照する方法

Posted at

はじめに

railsのポートフォリオ作成中に親model、子model、孫modelとあって
親の全部の子から特定の孫を抽出するのにかなり苦労したので残しておくことにしました。

以下の例では、親モデル:Parent、 子モデル:Child、 孫モデル:Grandchild として説明します。
また、親:子 = 1:N、 子:孫 = 1:N とします。

前提

今回のmodel操作は,

親:子:孫 = 1:全部(all):全部 or 特定 (where) を実現する方法なので、
親:子:孫 = 1:特定  : 全部 or 特定 ではありませんので予めご理解ください

一般的な連結

#親モデル parent.rb
Class Parent < ApplicationRecord
 has_many   :childs
end

#子モデル child.rb
Class Child < ApplicationRecord
 belongs_to :parent
 has_many   :grandchilds
end

#孫モデル grand_child.rb
Class Grandchild < ApplicationRecord
 belongs_to :child
end

#model作成時に子モデルにparent:references、
#孫モデルにchild:referencesが含まれていることが前提です

これで一般的な連携が可能となります。

問題

ここでParentから全Childを取得して、さらにGrandChildを取得しようとすると


#rails console

> childs = Parents.first.childs.all
=> #<ActiveRecord::AssociationRelation [ #<Child id:1, ...> ... ]

> grandchilds = childs.grandchilds.all
=> NoMethodError (undefined method "grandchilds" 
for #<Child::ActiveRecord_AssociationRelation:000000000000000000)

と怒られてしまいます←
なので関連付けを追加する必要があります。

親から孫に直接アクセスする(結論)

model
#親モデル parent.rb
class Parent < ApplicationRecord
 has_many   :childs
 has_many   :Grandchild, through: :childs  #<=これを追加!!!
end

#子モデル child.rb
変更なし

#孫モデル grand_child.rb
class Grandchild < ApplicationRecord
 belongs_to :child
 has_one    :master,  through: :child      #<=これも追加!!!
end

これで直接の取得が可能になりました!

#rails console

> grandchilds = Parents.first.grandchilds.all
=> #<ActiveRecord::AssociationRelation [ #<GrandChild id:1, ...> ... ]

こんなに簡単なのに2、3日かかってしまった。。

最後に

今回の表記は一番初歩的な書き方だったので今後はN+1とかも考慮した書き方を学んでいきたいですね!
また、前提で触れた「特定の複数子モデルに対しての孫アクセス」も機会があればやりたいと思います。

では!

7
3
2

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
7
3