当方、ActiveRecord(Rails)初心者ですがこんな感じかなというのをメモします。
準備
$ rails g model category name:string parent_category_id:integer
$ rake db:migrate
mysql> select * from categories;
+----+---------+--------------------+---------------------+---------------------+
| id | name | parent_category_id | created_at | updated_at |
+----+---------+--------------------+---------------------+---------------------+
| 1 | metal | NULL | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
| 2 | melodic | 1 | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
| 3 | black | 1 | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
| 4 | death | 1 | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
| 5 | jazz | NULL | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
| 6 | swing | 5 | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
| 7 | modern | 5 | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
| 8 | bebop | 5 | 2014-12-27 09:38:14 | 2014-12-27 09:38:14 |
+----+---------+--------------------+---------------------+---------------------+
Model定義
class Category < ActiveRecord::Base
has_many :children, class_name: "Category", foreign_key: "parent_category_id"
belongs_to :parent, class_name: "Category", foreign_key: "parent_category_id"
end
確認
$ rails console
> Category.first
=> #<Category id: 1, name: "metal", parent_category_id: nil, created_at: "2014-12-27 08:26:48", updated_at: "2014-12-27 08:26:48">
> Category.first.children
=> #<ActiveRecord::Associations::CollectionProxy [#<Category id: 2, name: "melodic", parent_category_id: 1, created_at: "2014-12-27 08:27:51", updated_at: "2014-12-27 08:27:51">, #<Category id: 3, name: "black", parent_category_id: 1, created_at: "2014-12-27 08:28:27", updated_at: "2014-12-27 08:28:27">, #<Category id: 4, name: "death", parent_category_id: 1, created_at: "2014-12-27 08:29:03", updated_at: "2014-12-27 08:29:03">]>
> Category.last
=> #<Category id: 8, name: "bebop", parent_category_id: 5, created_at: "2014-12-27 08:40:14", updated_at: "2014-12-27 08:40:14">
> Category.last.parent
=> #<Category id: 8, name: "bebop", parent_category_id: 5, created_at: "2014-12-27 08:40:14", updated_at: "2014-12-27 08:40:14">
便利な gem があったりするんでしょうか。
※追記
Active Record Associations
2.10 Self Joins
http://guides.rubyonrails.org/association_basics.html#self-joins
↑を見つけました。こちらの方が t.references で参照しているので良いですね。
「Self Joins」って書いてあったので自己結合してるのかと思ったんですが違いました。
> Category.last
Category Load (0.2ms) SELECT `categories`.* FROM `categories` ORDER BY `categories`.`id` DESC LIMIT 1
> Category.last.parent
Category Load (0.3ms) SELECT `categories`.* FROM `categories` ORDER BY `categories`.`id` DESC LIMIT 1
Category Load (0.3ms) SELECT `categories`.* FROM `categories` WHERE `categories`.`id` = 5 LIMIT 1
※追記2
@jnchito さんにコメントで教えていただいた Ancestry について投稿しました。
ActiveRecordで多階層カテゴリ(Ancestry)