スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Rails model 階層化

Railsのモデルを自己階層化(?)したい場合――といってもたぶん伝わらないと思いますが、つまり、こういうこと↓

├机 ─デスク
├椅子┬スツール
│  └座椅子
└布団


階層の数が決まってれば、階層数だけテーブルとモデルを作ってリレーション設定してもいいんですが、スケーラビリティ的にあまり嬉しくない。
どうせ複数階層対応するなら、無限階層まで対応したい。

というわけで、CategoryモデルからCategoryモデルにリレーションを張って、自己階層化(?)したいわけです。


イメージとしてはこうですね↓

rails_root/app/model/category.rb
class Category < ActiveRecord::Base
belongs_to :category
has_many :categories
end

とはいえ、これだと動きません。


こういう状況を扱う方法はリファレンス本にも載っていなくて、必死にググった結果、見つけたのが下のページ。あなたが神か。

参考:日本の天ぷら情報「Railsで階層構造のデータを自力で扱う」

しかし、神も全能ではないらしく、うまく行かない点がいくつかあったので、そのあたりを書いておきます。

ちなみに、リンク先にもありますが、こういうデータ構造を「隣接リストモデル」とかって言うらしいです。ほへぇー。


【0】とりあえず、環境

Rails:3.2.0


【1】テスト用のアプリケーションの作成

テスト用のアプリケーションを作成します。

$ rails new tree_test
$ cd tree_test/
$ rails generate scaffold category name:string parent_id:integer
$ rake db:migrate



モデルを編集します。

rails_root/app/models/category.rb
class Category < ActiveRecord::Base
belongs_to :parent, class_name: Category, foreign_key: "parent_id"
has_many :children, class_name: Category, foreign_key: "parent_id"
end


これで、@category.name するのと同じように @category.parent.name したりできるようになります。

あと、@category.children.each とか。


ちなみに、冒頭の
├机 ─デスク
├椅子┬スツール
│  └座椅子
└布団
をこのモデルで表すと、
| id | name   | parent_id |
| 1 | 机    | nil |
| 2 | 椅子   | nil |
| 3 | 布団   | nil |
| 4 | デスク  | 1     |
| 5 | スツール | 2     |
| 6 | 座椅子  | 2     |
な感じになります。

コメントの投稿

非公開コメント

カレンダー
07 | 2017/08 | 09
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -
検索フォーム
カテゴリ
月別アーカイブ
最新記事
最新コメント
最新トラックバック
RSSリンクの表示
QRコード
QR
リンク
アクセス解析
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。