acts_as_sane_tree 1.0 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ === v1.1
2
+ * New class method nodes_and_descendents
3
+ * Updated instance method #descendents to call class method nodes_and_descendents
4
+
5
+ === v1.0
6
+ * Initial release
@@ -22,8 +22,13 @@ A few extras are provided. Of note are:
22
22
 
23
23
  * #depth -> depth from root of the current node
24
24
  * #descendents -> all descendents of the current node (provided in either flat array or nested hash)
25
- * nodes_within? -> true if any of the nodes provided in the first parameter are found within the selfs or descendents of the second parameter
26
- * nodes_within -> same as #nodes_within? but returns array of found nodes
25
+ * nodes_within?(src, chk) - Returns true if chk contains any nodes found within src and all ancestors of nodes within src
26
+ * nodes_within(src, chk) - Returns any matching nodes from chk found within src and all ancestors within src
27
+ * nodes_and_descendents(*args) - Returns all nodes and descendents for given IDs or records.
28
+
29
+ == Documentation
30
+
31
+ http://chrisroberts.github.com/acts_as_sane_tree
27
32
 
28
33
  == Thanks
29
34
 
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  acts_as_sane_tree.gemspec
17
17
  init.rb
18
18
  README.rdoc
19
+ CHANGELOG.rdoc
19
20
  lib/acts_as_sane_tree.rb
20
21
  lib/version.rb
21
22
  }
@@ -1,5 +1,6 @@
1
1
  module ActsAsSaneTree
2
- def self.included(base)
2
+
3
+ def self.included(base) # :nodoc:
3
4
  base.extend(ClassMethods)
4
5
  end
5
6
 
@@ -25,13 +26,14 @@ module ActsAsSaneTree
25
26
  # root.children # => [child1]
26
27
  # root.children.first.children.first # => subchild1
27
28
  #
28
- # In addition to the parent and children associations, the following instance methods are added to the class
29
- # after calling <tt>acts_as_sane_tree</tt>:
30
- # * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>)
31
- # * <tt>self_and_siblings</tt> - Returns all the children of the parent, including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>)
32
- # * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
33
- # * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>)
34
- # * <tt>nodes_within?(src, chk)</tt> - Returns true if any nodes provided in chk are found within the nodes in src or the descendents of the nodes in chk
29
+ # The following class methods are also added:
30
+ #
31
+ # * <tt>nodes_within?(src, chk)</tt> - Returns true if chk contains any nodes found within src and all ancestors of nodes within src
32
+ # * <tt>nodes_within(src, chk)</tt> - Returns any matching nodes from chk found within src and all ancestors within src
33
+ # * <tt>nodes_and_descendents(*args)</tt> - Returns all nodes and descendents for given IDs or records. Accepts multiple IDs and records. Valid options:
34
+ # * :raw - No Hash nesting
35
+ # * :no_self - Will not return given nodes in result set
36
+ # * {:depth => n} - Will set maximum depth to query
35
37
  module ClassMethods
36
38
  # Configuration options are:
37
39
  #
@@ -88,6 +90,40 @@ module ActsAsSaneTree
88
90
  )
89
91
  end
90
92
  end
93
+
94
+ def self.nodes_and_descendents(*args)
95
+ raw = args.delete(:raw)
96
+ no_self = args.delete(:no_self)
97
+ depth = args.detect{|x|x.is_a?(Hash)}
98
+ if(depth)
99
+ args.delete(depth)
100
+ depth = depth[:depth]
101
+ end
102
+ base_ids = args.map{|x| x.is_a?(ActiveRecord::Base) ? x.id : x.to_i}
103
+ q = self.find_by_sql(
104
+ "WITH RECURSIVE crumbs AS (
105
+ SELECT #{self.table_name}.*, \#{no_self ? -1 : 0} AS level FROM #{self.table_name} WHERE id in (\#{base_ids.join(', ')})
106
+ UNION ALL
107
+ SELECT alias1.*, crumbs.level + 1 FROM crumbs JOIN #{self.table_name} alias1 on alias1.parent_id = crumbs.id
108
+ \#{depth ? "WHERE crumbs.level + 1 < \#{depth.to_i}" : ''}
109
+ ) SELECT * FROM crumbs WHERE level >= 0 ORDER BY level, parent_id ASC"
110
+ )
111
+ unless(raw)
112
+ res = {}
113
+ cache = {}
114
+ q.each do |item|
115
+ cache[item.id] = {}
116
+ if(cache[item.parent_id])
117
+ cache[item.parent_id][item] = cache[item.id]
118
+ else
119
+ res[item] = cache[item.id]
120
+ end
121
+ end
122
+ res
123
+ else
124
+ q
125
+ end
126
+ end
91
127
 
92
128
  EOV
93
129
  end
@@ -143,45 +179,20 @@ module ActsAsSaneTree
143
179
  # \_ subchild2
144
180
  # the resulting hash would look like:
145
181
  #
146
- # -> {child1 =>
147
- # {subchild1 =>
148
- # {subsubchild1 => {}},
149
- # subchild2 => {}}}
182
+ # {child1 =>
183
+ # {subchild1 =>
184
+ # {subsubchild1 => {}},
185
+ # subchild2 => {}}}
150
186
  #
151
187
  # This method will accept two parameters.
152
188
  # * :raw -> Result is flat array. No Hash tree is built
153
189
  # * {:depth => n} -> Will only search for descendents to the given depth of n
154
190
  def descendents(*args)
155
- depth = args.detect{|x|x.is_a?(Hash) && x[:depth]}
156
- depth = depth[:depth] if depth
157
- raw = args.include?(:raw)
158
- q = self.class.find_by_sql(
159
- "WITH RECURSIVE crumbs AS (
160
- SELECT #{self.class.table_name}.*, -1 AS level FROM #{self.class.table_name} WHERE id = #{id}
161
- UNION ALL
162
- SELECT alias1.*, crumbs.level + 1 FROM crumbs JOIN #{self.class.table_name} alias1 on alias1.parent_id = crumbs.id
163
- #{depth ? "WHERE crumbs.level + 1 < #{depth.to_i}" : ''}
164
- ) SELECT * FROM crumbs WHERE level >= 0 ORDER BY level, parent_id ASC"
165
- )
166
- unless(raw)
167
- res = {}
168
- cache = {}
169
- q.each do |item|
170
- cache[item.id] = {}
171
- if(cache[item.parent_id])
172
- cache[item.parent_id][item] = cache[item.id]
173
- else
174
- res[item] = cache[item.id]
175
- end
176
- end
177
- res
178
- else
179
- q
180
- end
191
+ args.delete_if{|x| !x.is_a?(Hash) && x != :raw}
192
+ self.class.nodes_and_descendents(:no_self, self, *args)
181
193
  end
182
194
 
183
- # Returns the depth of the current node. 0 depth represents the root
184
- # of the tree
195
+ # Returns the depth of the current node. 0 depth represents the root of the tree
185
196
  def depth
186
197
  res = self.class.connection.select_all(
187
198
  "WITH RECURSIVE crumbs AS (
@@ -1,3 +1,3 @@
1
1
  module ActsAsSaneTree
2
- VERSION = '1.0'
2
+ VERSION = '1.1'
3
3
  end
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_sane_tree
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 13
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
- - 0
9
- version: "1.0"
8
+ - 1
9
+ version: "1.1"
10
10
  platform: ruby
11
11
  authors:
12
12
  - Chris Roberts
@@ -43,6 +43,7 @@ files:
43
43
  - acts_as_sane_tree.gemspec
44
44
  - init.rb
45
45
  - README.rdoc
46
+ - CHANGELOG.rdoc
46
47
  - lib/acts_as_sane_tree.rb
47
48
  - lib/version.rb
48
49
  has_rdoc: true