#はじめに
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)
と怒られてしまいます←
なので関連付けを追加する必要があります。
#親から孫に直接アクセスする(結論)
#親モデル 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とかも考慮した書き方を学んでいきたいですね!
また、前提で触れた「特定の複数子モデルに対しての孫アクセス」も機会があればやりたいと思います。
では!