概要
- ツリー構造の実装のためのclosure_treeを使ってみました
環境
- rails 6
背景
部署の上下構造を表現するために導入しました
今回対象とした部署のテーブル名は organizations
です
手順
インストール
普通に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 テーブル
- organization_hierarchie テーブル
- ツリー構造を削除するには
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直下に付け替え
以上