acts_as_sane_tree 1.0 → 1.1

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.
@@ -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