LoginSignup
9
4

More than 3 years have passed since last update.

closure_treeでツリー構造

Posted at

概要

  • ツリー構造の実装のためのclosure_treeを使ってみました

環境

  • rails 6

背景

部署の上下構造を表現するために導入しました
今回対象とした部署のテーブル名は organizations です

image.png

手順

インストール

普通にgemをインストールします

gem 'closure_tree'
bundle install

マイグレーション

ツリー構造を追加したいモデルに has_closure_tree を追加します。

app/models/organization.rb
class Organization < ApplicationRecord
  has_closure_tree
end

ここを見ながら 、必要なmigrationを追加します。

rails g closure_tree:migration organization 

下記のファイルが追加されます

db/migrate/20190430101958_create_organization_hierarchies.rb
class CreateOrganizationHierarchies < ActiveRecord::Migration[6.0]
  def change
    create_table :organization_hierarchies, id: false do |t|
      t.integer :ancestor_id, null: false
      t.integer :descendant_id, null: false
      t.integer :generations, null: false
    end

    add_index :organization_hierarchies, [:ancestor_id, :descendant_id, :generations],
      unique: true,
      name: "organization_anc_desc_idx"

    add_index :organization_hierarchies, [:descendant_id],
      name: "organization_desc_idx"
  end
end
rails g migration AddParentIdToOrganization 

add_column :organizations, :parent_id, :integer を追加します

db/migrate/20190430102217_add_parent_id_to_organization.rb
class AddParentIdToOrganization < ActiveRecord::Migration[6.0]
  def change
    add_column :organizations, :parent_id, :integer
  end
end
rail g db:migration

これで準備完了です。

使い方

既存のデータにツリー構造を付与

適当に rails c を起動します。

  • add_child でツリー構造を付与します。
irb> bucho_a = Organization.find(1)
irb> kacho_a = Organization.find(2)
irb> kakaricho_a = Organization.find(3)
irb> kakaricho_b = Organization.find(4)

irb> bucho_a.add_child(kacho_a)
irb> kacho_a.add_child(kakaricho_a)
irb> kacho_a.add_child(kakaricho_b)

上記コマンドを打つと、テーブルは下記のようになります。

  • organizations テーブル

image.png

  • organization_hierarchie テーブル

image.png

  • ツリー構造を削除するには parent_id を修正してください。 (参考) 関連する organization_hierarchie テーブル もあわせて修正されます。
irb> kakaricho_a = Organization.find(3)
irb> kakaricho_a.update(parent_id: nil)
  • ツリーをつけかえるには、おなじく parent_id を修正してください。
irb> kakaricho_b = Organization.find(3)
irb>kakaricho_b.update(parent_id: 1) # 課長Aから部長B直下に付け替え

以上

9
4
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
9
4