5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RailsにおけるN:Nの自己結合

5
Last updated at Posted at 2018-02-23

はじめに

自己結合のサンプルとしてディレクトリツリーの表現を考える。

備忘録になってしまっているので、まとめ直したいところ。

ディレクトリツリーの表現

ディレクトリツリーをモデルで表現する場合以下のような設定を行う。

class Directory < ActiveRecord::Base
  has_one :parent,      through: :parent_tree, source: :parent                        
  has_one :parent_tree, class_name: "DirectoryTree", foreign_key: :child_id

  has_many :children,     through: :child_trees,  source: :child
  has_many :child_trees,  class_name: "DirectoryTree", foreign_key: :parent_id
end
  
class DirectoryTree < ActiveRecord::Base
  belongs_to :parent, class_name: "Directory"
  belongs_to :child,  class_name: "Directory"
end

@directory にDirectoryモデルのインスタンスが格納されているとして、
親ディレクトリの関連(DirectorTree)は @directory.parent_tree で取得。
親ディレクトリ自体(Directory)は @directory.parent で取得。

この説明だけで、定義の意味を理解できる人はどれだけいるだろうか。
個人的に定義が素直に頭に入らない理由が2つある。

1つ目: foreign_keyが自身と関連先のモデルのどちらを指しているのか分からないから

答えとしては、

  • belongs_toで定義するforeign_keyは自身のカラムを指定。
  • has_manyで定義するforeign_keyは関連先のモデルのカラムを指定。

だが、理解するのに大分時間がかかった。

なおhas_manyの場合、foreign_keyの設定がないと、関連付ける外部キーの名前は「自身モデル名_id(例ではdirectory_id)」となるが、
参照先のモデルにはDrectoryモデルのidを示すカラムがparent_idとchild_idとして分けて定義しているので、どちらに紐づくのかを指定する必要がある。
この必要性を理解すればhas_manyのforeign_keyは関連先のモデルのカラムを指定することが自明なのだが、なかなか考えがまとまらなかった。。。

2つ目: sourceが自身と関連先のモデルのどちらを指しているのか分からないから

答えとしては、

  • 関連先のモデルを指定

だが、sourceという言葉自体に惑わされると理解が難しい。

以下のように定義を簡略化すれば、
配下のディレクトリを取得する場合には「:child_trees」を通して「:directory」を取得するという流れがわかりやすいかも。

class Directory < ActiveRecord::Base
  has_many :children,     through: :child_trees,  source: :directory
  has_many :child_trees,  class_name: "DirectoryTree", foreign_key: :parent_id
end
  
class DirectoryTree < ActiveRecord::Base
  belongs_to :directory
end

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?