treeable 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/treeable.rb +127 -0
  3. metadata +45 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 85fb68955146f887d08b6ca36529664c4b60cd2c
4
+ data.tar.gz: 7a0b4bb89f1306bbe67cf8eabcc01edeafc0a7bc
5
+ SHA512:
6
+ metadata.gz: a2d5c679d50d3921f2d499d008642c68766317db3eb93781f6d67eeef61b5451998e0023377a363aca31f24a96f0a9426b9717e7e58ac2fd5d823caa636a7ed3
7
+ data.tar.gz: f13ecadad4ccdf7c2b80fa6c498d59a59d96e4d7eb650f250e9fffe24a9867aa833fd9d215cc43fafae6c390397a959e917eb76963ca610b555dcea40c491752
data/lib/treeable.rb ADDED
@@ -0,0 +1,127 @@
1
+ module Treeable
2
+ extend ::ActiveSupport::Concern
3
+
4
+ included do
5
+
6
+ after_create :update_path
7
+ after_update :repopulate_path
8
+ belongs_to :parent, :class_name => self.to_s, :foreign_key => :parent_id
9
+ has_many :children, :class_name => self.to_s, :foreign_key=> :parent_id
10
+
11
+ @treeable_parent = :parent_id
12
+ @treeable_path = :path
13
+
14
+ def self.define_association
15
+ belongs_to :parent, :class_name => self.to_s, :foreign_key => @treeable_parent
16
+ has_many :children, :class_name => self.to_s, :foreign_key=> @treeable_parent
17
+ end
18
+
19
+ def self.treeable_path_column(column_name=nil)
20
+ if column_name
21
+ @treeable_path = column_name.to_sym
22
+ end
23
+ return @treeable_path
24
+ end
25
+
26
+
27
+ def self.treeable_parent_column(column_name=nil)
28
+ if column_name
29
+ @treeable_parent = column_name.to_sym
30
+ self.define_association
31
+ end
32
+ return @treeable_parent
33
+ end
34
+
35
+ def self.json_tree(nodes)
36
+ nodes.map do |node|
37
+ {:id => node.id, :children => json_tree(node.children)}
38
+ end
39
+ end
40
+
41
+ def self.roots
42
+ where(@treeable_parent => nil)
43
+ end
44
+
45
+ def self.leaves
46
+ array = []
47
+ roots.each do |k|
48
+ array += k.leafs
49
+ end
50
+ self.where(id: (array.uniq.compact))
51
+ end
52
+ end
53
+
54
+ def path
55
+ if !self.attributes.keys.include?("path") && self.class.treeable_path_column !="path"
56
+ send(self.class.treeable_path_column)
57
+ end
58
+ end
59
+
60
+ def is_leaf
61
+ self.children.empty?
62
+ end
63
+
64
+ def is_root
65
+ self.parent.blank?
66
+ end
67
+
68
+ def parent_map(&block)
69
+ (nodes_from_root || []).each{|k| block.call k}
70
+ end
71
+
72
+ def children_map(&block)
73
+ unless all_children.empty?
74
+ children.each{|k| k.children_map(&block)}
75
+ end
76
+ end
77
+
78
+ def leafs
79
+ array = []
80
+ if self.is_leaf
81
+ array << self.id
82
+ else
83
+ parent_ids = self.all_children.where(self.class.treeable_parent_column => (all_children_ids << self.id)).pluck(self.class.treeable_parent_column)
84
+ array += self.all_children_ids - parent_ids
85
+ end
86
+ array
87
+ end
88
+
89
+ def leaf_nodes
90
+ internal_nodes = self.class.where(self.class.treeable_parent_column => self.all_children_ids).select(self.class.treeable_parent_column).group(self.class.treeable_parent_column).pluck(self.class.treeable_parent_column)
91
+ self.all_children.map{|t| t unless internal_nodes.include?(t[:id])}.uniq.compact
92
+ end
93
+
94
+ def node_ids_from_root
95
+ self.path.split(".").map{|k| k.to_i}
96
+ end
97
+
98
+ def nodes_from_root
99
+ self.class.where(:id => node_ids_from_root).order("length(#{self.class.treeable_path_column.to_s}) ASC")
100
+ end
101
+
102
+ def all_children
103
+ self.class.where("#{self.class.treeable_path_column} LIKE '#{self.path}%'").where.not(:id => self.id)
104
+ end
105
+
106
+ def all_children_ids
107
+ all_children.pluck(:id)
108
+ end
109
+
110
+ def repopulate_path
111
+ if self.parent_id_changed?
112
+ child_nodes = all_children
113
+ path = parent ? "#{parent.path}#{self.id}." : "#{self.id}."
114
+ self.update_column(self.class.treeable_path_column.to_s, path)
115
+ child_nodes.each{|k| k.update_path}
116
+ end
117
+ end
118
+
119
+ def update_path
120
+ new_path = self.parent ? "#{self.parent.path}#{self.id}." : "#{self.id}."
121
+ self.update_column(self.class.treeable_path_column.to_s, new_path)
122
+ end
123
+
124
+ def root
125
+ self.path.split('.').first.to_i
126
+ end
127
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: treeable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Saurav Swaroop
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-14 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple hello world gem
14
+ email: swaroop.saurav.s@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/treeable.rb
20
+ homepage: http://rubygems.org/gems/hola
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.6.12
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Making any Rails model treeable. Any model is Treeable if it has parent chuld
44
+ relation with itself
45
+ test_files: []