LoginSignup
18
20

More than 5 years have passed since last update.

ActiveRecordで多階層カテゴリ

Last updated at Posted at 2014-12-27

当方、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)

18
20
4

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
18
20