treeable 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []