Ruby on Rails Self-referential has_many :through associations

第二十六回

というわけで,Railsで自己参照多対多アソシエーションをhas_many :throughを利用して実装してみるメモ.
今回用意したサンプルはWebページがリンクで繋がってるイメージ.ERDは以下の画像みたいな感じ.

それぞれのmodelはこんな感じ.

class Page < ActiveRecord::Base
  # Associations
  has_many :links_sent, :foreign_key => 'from_page_id', :class_name => 'Link', :dependent => :destroy
  has_many :links_received, :foreign_key => 'to_page_id', :class_name => 'Link', :dependent => :destroy
  has_many :links_sent_pages, :through => :links_sent, :source => :link_to_page
  has_many :links_received_pages, :through => :links_received, :source => :link_from_page

  # validates
  validates_uniqueness_of :url
end
class Link < ActiveRecord::Base
  # Associations
  belongs_to :link_from_page, :foreign_key => 'from_page_id', :class_name => 'Page'
  belongs_to :link_to_page, :foreign_key => 'to_page_id', :class_name => 'Page'
end

script/consoleで確認してみる.

Link主体で作成する場合

ruby script/console
>> Page.count
=> 0
>> from_page = Page.new(:url => "http://example.com/page/from")
>> to_page = Page.new(:url => "http://example.com/page/to")
>> to_page.links_received_pages
=> []
>> Link.create(:link_from_page => from_page, :link_to_page => to_page)
>> to_page.links_received_pages
=> [#<Page:0xb7ae42ac @attributes={"body"=>nil, "url"=>"http://example.com/page/from", "id"=>"1"}>]
>> Page.count
=> 2
>> Link.count
=> 1

Page主体で作成する場合

ruby script/console
>> Page.count
=> 0
>> from_page = Page.create(:url => "http://example.com/page/from")
>> from_page.links_sent_pages
=> []
>> from_page.links_sent.create(:link_to_page => Page.new(:url => "http://example.com/page/to"))
>> from_page.links_sent_pages
=> [#<Page:0xb7ca56c0 @attributes={"body"=>nil, "url"=>"http://example.com/page/to", "id"=>"2"}>]
>> Page.count
=> 2
>> Link.count
=> 1

削除してみる.(上の続き)

ruby script/console
>> Page.count
=> 2
>> Link.count
=> 1
>> from_page.destroy
>> Page.count
=> 1
>> Link.count
=> 0

この単純なモデルならhabtm使えばいいんだけど,これからはhas_many :throughが流行らしいので.
今回のサンプルでは載せてないけど,実際に作る際にはLinkも他のモデルと関連してるんでこっちでいってみた.

コツは,has_manyの第1引数に与える名前を分かりやすくすること!!絶対にどっちがリンク元?リンク先?って混乱するから(経験者語る)

おしまい