parndt-acts_as_tree 1.2.5

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,38 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/*_test.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ begin
12
+ require 'rcov/rcovtask'
13
+ Rcov::RcovTask.new do |test|
14
+ test.libs << 'test'
15
+ test.pattern = 'test/**/*_test.rb'
16
+ test.verbose = true
17
+ end
18
+ rescue LoadError
19
+ task :rcov do
20
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
21
+ end
22
+ end
23
+
24
+ task :default => :test
25
+
26
+ require 'rake/rdoctask'
27
+ Rake::RDocTask.new do |rdoc|
28
+ if File.exist?('VERSION')
29
+ version = File.read('VERSION')
30
+ else
31
+ version = ""
32
+ end
33
+
34
+ rdoc.rdoc_dir = 'rdoc'
35
+ rdoc.title = "acts_as_tree #{version}"
36
+ rdoc.rdoc_files.include('README*')
37
+ rdoc.rdoc_files.include('lib/**/*.rb')
38
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.2.5
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'acts_as_tree'
@@ -0,0 +1,193 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module Tree
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ # Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
9
+ # association. This requires that you have a foreign key column, which by default is called +parent_id+.
10
+ #
11
+ # class Category < ActiveRecord::Base
12
+ # acts_as_tree :order => "name"
13
+ # end
14
+ #
15
+ # Example:
16
+ # root
17
+ # \_ child1
18
+ # \_ subchild1
19
+ # \_ subchild2
20
+ #
21
+ # root = Category.create("name" => "root")
22
+ # child1 = root.children.create("name" => "child1")
23
+ # subchild1 = child1.children.create("name" => "subchild1")
24
+ #
25
+ # root.parent # => nil
26
+ # child1.parent # => root
27
+ # root.children # => [child1]
28
+ # root.children.first.children.first # => subchild1
29
+ #
30
+ # In addition to the parent and children associations, the following instance methods are added to the class
31
+ # after calling <tt>acts_as_tree</tt>:
32
+ # * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>)
33
+ # * <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>)
34
+ # * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
35
+ # * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>)
36
+ # * <tt>descendants</tt> - Returns a flat list of the descendants of the current node (<tt>[child1, subchild1, subchild2]</tt> when called on <tt>root</tt>)
37
+ module ClassMethods
38
+ # Configuration options are:
39
+ #
40
+ # * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+)
41
+ # * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
42
+ # * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+).
43
+ # * <tt>include</tt> - ability to add eager loading to tree finds by specifying associations to include. 'children' association eager loaded by default. Disable by supplying :include => nil or :include => []
44
+ def acts_as_tree(options = {})
45
+ configuration = {
46
+ :foreign_key => "parent_id",
47
+ :order => nil,
48
+ :counter_cache => nil,
49
+ :dependent => :destroy,
50
+ :touch => false,
51
+ :include => [:children]
52
+ }
53
+ configuration.update(options) if options.is_a?(Hash)
54
+ configuration.update({:include => []}) if configuration[:include].nil? # if calling class really doesn't want to eager load its children.
55
+
56
+ belongs_to :parent,
57
+ :class_name => name,
58
+ :foreign_key => configuration[:foreign_key],
59
+ :counter_cache => configuration[:counter_cache],
60
+ :inverse_of => :children,
61
+ :touch => configuration[:touch]
62
+
63
+ has_many :children,
64
+ :class_name => name,
65
+ :foreign_key => configuration[:foreign_key],
66
+ :order => configuration[:order],
67
+ :dependent => configuration[:dependent],
68
+ :include => configuration[:include],
69
+ :inverse_of => :parent
70
+
71
+ class_eval <<-EOV
72
+ include ActiveRecord::Acts::Tree::InstanceMethods
73
+
74
+ scope :roots,
75
+ :conditions => "#{configuration[:foreign_key]} IS NULL",
76
+ :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}},
77
+ :include => %W{#{configuration[:include].join(' ')}}
78
+
79
+ after_save :update_level_cache
80
+ after_update :update_parents_counter_cache
81
+
82
+ def self.root
83
+ roots.first
84
+ end
85
+
86
+ def self.childless
87
+ nodes = []
88
+
89
+ find(:all, :include => configuration[:include]).each do |node|
90
+ nodes << node if node.children.empty?
91
+ end
92
+
93
+ nodes
94
+ end
95
+
96
+ validates_each "#{configuration[:foreign_key]}" do |record, attr, value|
97
+ if value
98
+ if record.id == value
99
+ record.errors.add attr, "cannot be it's own id"
100
+ elsif record.descendants.map {|c| c.id}.include?(value)
101
+ record.errors.add attr, "cannot be a descendant's id"
102
+ end
103
+ end
104
+ end
105
+ EOV
106
+ end
107
+ end
108
+
109
+ module InstanceMethods
110
+ # Returns list of ancestors, starting from parent until root.
111
+ #
112
+ # subchild1.ancestors # => [child1, root]
113
+ def ancestors
114
+ node, nodes = self, []
115
+ nodes << node = node.parent until node.parent.nil? and return nodes
116
+ end
117
+
118
+ def root?
119
+ parent == nil
120
+ end
121
+
122
+ def leaf?
123
+ children.length == 0
124
+ end
125
+
126
+ # Returns the root node of the tree.
127
+ def root
128
+ node = self
129
+ node = node.parent until node.parent.nil? and return node
130
+ end
131
+
132
+ # Returns all siblings of the current node.
133
+ #
134
+ # subchild1.siblings # => [subchild2]
135
+ def siblings
136
+ self_and_siblings - [self]
137
+ end
138
+
139
+ # Returns all siblings and a reference to the current node.
140
+ #
141
+ # subchild1.self_and_siblings # => [subchild1, subchild2]
142
+ def self_and_siblings(node = self)
143
+ node.parent.present? ? node.parent.reload.children : node.class.roots
144
+ end
145
+
146
+ # Returns a flat list of the descendants of the current node.
147
+ #
148
+ # root.descendants # => [child1, subchild1, subchild2]
149
+ def descendants(node=self)
150
+ nodes = []
151
+ nodes << node unless node == self
152
+
153
+ node.children.each do |child|
154
+ nodes += descendants(child)
155
+ end
156
+
157
+ nodes.compact
158
+ end
159
+
160
+ def chain
161
+ [self.ancestors, self, self.descendants].flatten
162
+ end
163
+
164
+ # Returns a flat list of all of the children under the current node
165
+ # which don't have any children belonging to them (childless)
166
+ #
167
+ # node.childess # => [subchild1, subchild2]
168
+ def childless
169
+ self.descendants.reject{|d| d.children.any?}
170
+ end
171
+
172
+ private
173
+
174
+ def update_parents_counter_cache
175
+ if self.respond_to?(:children_count) && parent_id_changed?
176
+ self.class.decrement_counter(:children_count, parent_id_was)
177
+ self.class.increment_counter(:children_count, parent_id)
178
+ end
179
+ end
180
+
181
+ def update_level_cache
182
+ if respond_to?(:level_cache) && parent_id_changed?
183
+ _level_cache = ancestors.length
184
+
185
+ if level_cache != _level_cache
186
+ self.class.update_all("level_cache = #{_level_cache}", ['id = ?', id])
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,2 @@
1
+ require File.expand_path('../active_record/acts/tree', __FILE__)
2
+ ActiveRecord::Base.send :include, ActiveRecord::Acts::Tree
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ version = File.open(File.expand_path('../../VERSION', __FILE__)).read.strip
3
+ raise "Could not get version so gemspec can not be built" if version.nil?
4
+ files = Dir.glob("**/*").flatten.reject do |file|
5
+ file =~ /\.gem(spec)?$/
6
+ end
7
+
8
+ gemspec = <<EOF
9
+ Gem::Specification.new do |s|
10
+ s.name = %q{parndt-acts_as_tree}
11
+ s.version = %q{#{version}}
12
+ s.description = %q{Use this acts_as extension if you want to model a tree structure by providing a parent association and a children
13
+ association.}
14
+ s.date = %q{#{Time.now.strftime('%Y-%m-%d')}}
15
+ s.summary = %q{acts_as_tree plugin.}
16
+ s.homepage = %q{http://philiparndt.name}
17
+ s.authors = ["David Heinemeier Hansson", "Philip Arndt", "Others"]
18
+ s.require_paths = %w(lib)
19
+
20
+ s.files = [
21
+ '#{files.join("',\n '")}'
22
+ ]
23
+ #{"s.test_files = [
24
+ '#{Dir.glob("test/**/*.rb").join("',\n '")}'
25
+ ]" if File.directory?("test")}
26
+ end
27
+ EOF
28
+
29
+ File.open(File.expand_path("../../parndt-acts_as_tree.gemspec", __FILE__), 'w').puts(gemspec)
@@ -0,0 +1 @@
1
+ require 'acts_as_tree'
@@ -0,0 +1,30 @@
1
+ h1. acts_as_tree (for rails3)
2
+
3
+ Specify this __acts_as__ extension if you want to model a tree structure by providing a parent association and a children
4
+ association. This requires that you have a foreign key column, which by default is called __parent_id__.
5
+
6
+ <notextile>
7
+ <pre><code>class Category < ActiveRecord::Base
8
+ acts_as_tree :order => "name"
9
+ end</code></pre>
10
+ </notextile>
11
+
12
+ h2. Example
13
+
14
+ <notextile>
15
+ <pre><code>root
16
+ \_ child1
17
+ \_ subchild1
18
+ \_ subchild2
19
+
20
+ root = Category.create("name" => "root")
21
+ child1 = root.children.create("name" => "child1")
22
+ subchild1 = child1.children.create("name" => "subchild1")
23
+
24
+ root.parent # => nil
25
+ child1.parent # => root
26
+ root.children # => [child1]
27
+ root.children.first.children.first # => subchild1</code></pre>
28
+ </notextile>
29
+
30
+ Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
@@ -0,0 +1,311 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+ require 'active_record'
5
+
6
+ $:.unshift File.expand_path('../../lib', __FILE__)
7
+ require File.expand_path('../../init.rb', __FILE__)
8
+
9
+ class Test::Unit::TestCase
10
+ def assert_queries(num = 1)
11
+ $query_count = 0
12
+ yield
13
+ ensure
14
+ assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
15
+ end
16
+
17
+ def assert_no_queries(&block)
18
+ assert_queries(0, &block)
19
+ end
20
+ end
21
+
22
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
23
+
24
+ # AR keeps printing annoying schema statements
25
+ $stdout_orig = $stdout
26
+ $stdout = StringIO.new
27
+
28
+ def setup_db
29
+ ActiveRecord::Base.logger
30
+ ActiveRecord::Schema.define(:version => 1) do
31
+ create_table :mixins do |t|
32
+ t.column :type, :string
33
+ t.column :parent_id, :integer
34
+ t.column :children_count, :integer, :default => 0
35
+ t.column :level_cache, :integer, :default => 0
36
+ end
37
+ end
38
+ end
39
+
40
+ def teardown_db
41
+ ActiveRecord::Base.connection.tables.each do |table|
42
+ ActiveRecord::Base.connection.drop_table(table)
43
+ end
44
+ end
45
+
46
+ class Mixin < ActiveRecord::Base
47
+ end
48
+
49
+ class TreeMixin < Mixin
50
+ acts_as_tree :foreign_key => "parent_id", :order => "id"
51
+ end
52
+
53
+ class TreeMixinWithCounterCache < Mixin
54
+ acts_as_tree :foreign_key => "parent_id", :order => "id", :counter_cache => :children_count
55
+ end
56
+
57
+ class TreeMixinWithoutOrder < Mixin
58
+ acts_as_tree :foreign_key => "parent_id"
59
+ end
60
+
61
+ class RecursivelyCascadedTreeMixin < Mixin
62
+ acts_as_tree :foreign_key => "parent_id"
63
+ has_one :first_child, :class_name => 'RecursivelyCascadedTreeMixin', :foreign_key => :parent_id
64
+ end
65
+
66
+ class TreeMixinNullify < Mixin
67
+ acts_as_tree :foreign_key => "parent_id", :order => "id", :dependent => :nullify
68
+ end
69
+
70
+ class TreeTest < Test::Unit::TestCase
71
+ def setup
72
+ setup_db
73
+ @root1 = TreeMixin.create!
74
+ @root_child1 = TreeMixin.create!(:parent => @root1)
75
+ @child1_child = TreeMixin.create!(:parent => @root_child1)
76
+ @root_child2 = TreeMixin.create!(:parent => @root1)
77
+ @root2 = TreeMixin.create!
78
+ @root3 = TreeMixin.create!
79
+ end
80
+
81
+ def teardown
82
+ teardown_db
83
+ end
84
+
85
+ def test_children
86
+ assert_equal @root1.reload.children, [@root_child1, @root_child2]
87
+ assert_equal @root_child1.reload.children, [@child1_child]
88
+ assert_equal @child1_child.reload.children, []
89
+ assert_equal @root_child2.reload.children, []
90
+ end
91
+
92
+ def test_parent
93
+ assert_equal @root_child1.parent, @root1
94
+ assert_equal @root_child1.parent, @root_child2.parent
95
+ assert_nil @root1.parent
96
+ end
97
+
98
+ def test_nullify
99
+ root4 = TreeMixinNullify.create!
100
+ root4_child = TreeMixinNullify.create!(:parent_id => root4.id)
101
+ assert_equal 2, TreeMixinNullify.count
102
+ assert_equal root4.id, root4_child.parent_id
103
+ root4.destroy
104
+ assert_equal 1, TreeMixinNullify.count
105
+ assert_nil root4_child.reload.parent_id
106
+ end
107
+
108
+ def test_delete
109
+ assert_equal 6, TreeMixin.count
110
+ @root1.destroy
111
+ assert_equal 2, TreeMixin.count
112
+ @root2.destroy
113
+ @root3.destroy
114
+ assert_equal 0, TreeMixin.count
115
+ end
116
+
117
+ def test_insert
118
+ @extra = @root1.children.create
119
+
120
+ assert @extra
121
+
122
+ assert_equal @extra.parent, @root1
123
+
124
+ assert_equal 3, @root1.reload.children.count
125
+ assert @root1.children.include?(@extra)
126
+ assert @root1.children.include?(@root_child1)
127
+ assert @root1.children.include?(@root_child2)
128
+ end
129
+
130
+ def test_ancestors
131
+ assert_equal [], @root1.ancestors
132
+ assert_equal [@root1], @root_child1.ancestors
133
+ assert_equal [@root_child1, @root1], @child1_child.ancestors
134
+ assert_equal [@root1], @root_child2.ancestors
135
+ assert_equal [], @root2.ancestors
136
+ assert_equal [], @root3.ancestors
137
+ end
138
+
139
+ def test_root
140
+ assert_equal @root1, TreeMixin.root
141
+ assert_equal @root1, @root1.root
142
+ assert_equal @root1, @root_child1.root
143
+ assert_equal @root1, @child1_child.root
144
+ assert_equal @root1, @root_child2.root
145
+ assert_equal @root2, @root2.root
146
+ assert_equal @root3, @root3.root
147
+ end
148
+
149
+ def test_roots
150
+ assert_equal [@root1, @root2, @root3], TreeMixin.roots
151
+ end
152
+
153
+ def test_siblings
154
+ assert_equal [@root2, @root3], @root1.siblings
155
+ assert_equal [@root_child2], @root_child1.siblings
156
+ assert_equal [], @child1_child.siblings
157
+ assert_equal [@root_child1], @root_child2.siblings
158
+ assert_equal [@root1, @root3], @root2.siblings
159
+ assert_equal [@root1, @root2], @root3.siblings
160
+ end
161
+
162
+ def test_self_and_siblings
163
+ assert_equal [@root1, @root2, @root3], @root1.self_and_siblings
164
+ assert_equal [@root_child1, @root_child2], @root_child1.self_and_siblings
165
+ assert_equal [@child1_child], @child1_child.self_and_siblings
166
+ assert_equal [@root_child1, @root_child2], @root_child2.self_and_siblings
167
+ assert_equal [@root1, @root2, @root3], @root2.self_and_siblings
168
+ assert_equal [@root1, @root2, @root3], @root3.self_and_siblings
169
+ end
170
+
171
+ def test_root
172
+ assert_equal true, @root1.root?
173
+ assert_equal false, @child1_child.root?
174
+ end
175
+
176
+ def test_leaf
177
+ assert_equal false, @root1.leaf?
178
+ assert_equal true, @child1_child.leaf?
179
+ end
180
+ end
181
+
182
+ class TreeTestWithCounterCache < Test::Unit::TestCase
183
+ def setup
184
+ teardown_db
185
+ setup_db
186
+ @root = TreeMixinWithCounterCache.create!
187
+ @child1 = TreeMixinWithCounterCache.create! :parent_id => @root.id
188
+ @child1_child1 = TreeMixinWithCounterCache.create! :parent_id => @child1.id
189
+ @child2 = TreeMixinWithCounterCache.create! :parent_id => @root.id
190
+ end
191
+
192
+ def teardown
193
+ teardown_db
194
+ end
195
+
196
+ def test_counter_cache
197
+ assert_equal 2, @root.reload.children_count
198
+ assert_equal 1, @child1.reload.children_count
199
+ end
200
+
201
+ def test_update_parents_counter_cache
202
+ @child1_child1.update_attributes(:parent_id => @root.id)
203
+ assert_equal 3, @root.reload.children_count
204
+ assert_equal 0, @child1.reload.children_count
205
+ end
206
+
207
+ end
208
+
209
+ class TreeTestWithLevelCache < Test::Unit::TestCase
210
+ def setup
211
+ teardown_db
212
+ setup_db
213
+ @root1 = TreeMixin.create!
214
+ @root_child1 = TreeMixin.create! :parent_id => @root1.id
215
+ @child1_child = TreeMixin.create! :parent_id => @root_child1.id
216
+ @root_child2 = TreeMixin.create! :parent_id => @root1.id
217
+ @root2 = TreeMixin.create!
218
+ end
219
+
220
+ def teardown
221
+ teardown_db
222
+ end
223
+
224
+ def test_level_cache
225
+ assert_equal 0, @root1.reload.level_cache
226
+ assert_equal 1, @root_child1.reload.level_cache
227
+ assert_equal 2, @child1_child.reload.level_cache
228
+ assert_equal 0, @root2.reload.level_cache
229
+ end
230
+
231
+ def test_level_cache_are_updated
232
+ @child1_child.reload.parent_id = nil
233
+ @child1_child.save
234
+
235
+ @root2.reload.parent_id = @root_child2.reload.id
236
+ @root2.save
237
+
238
+ assert_equal 0, @root1.reload.level_cache
239
+ assert_equal 1, @root_child1.reload.level_cache
240
+ assert_equal 0, @child1_child.reload.level_cache
241
+ assert_equal 2, @root2.reload.level_cache
242
+ end
243
+ end
244
+
245
+ class TreeTestWithEagerLoading < Test::Unit::TestCase
246
+
247
+ def setup
248
+ teardown_db
249
+ setup_db
250
+ @root1 = TreeMixin.create!
251
+ @root_child1 = TreeMixin.create! :parent_id => @root1.id
252
+ @child1_child = TreeMixin.create! :parent_id => @root_child1.id
253
+ @root_child2 = TreeMixin.create! :parent_id => @root1.id
254
+ @root2 = TreeMixin.create!
255
+ @root3 = TreeMixin.create!
256
+
257
+ @rc1 = RecursivelyCascadedTreeMixin.create!
258
+ @rc2 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc1.id
259
+ @rc3 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc2.id
260
+ @rc4 = RecursivelyCascadedTreeMixin.create! :parent_id => @rc3.id
261
+ end
262
+
263
+ def teardown
264
+ teardown_db
265
+ end
266
+
267
+ def test_eager_association_loading
268
+ roots = TreeMixin.find(:all, :include => :children, :conditions => "mixins.parent_id IS NULL", :order => "mixins.id")
269
+ assert_equal [@root1, @root2, @root3], roots
270
+ assert_no_queries do
271
+ assert_equal 2, roots[0].children.count
272
+ assert_equal 0, roots[1].children.count
273
+ assert_equal 0, roots[2].children.count
274
+ end
275
+ end
276
+
277
+ def test_eager_association_loading_with_recursive_cascading_three_levels_has_many
278
+ root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :children => { :children => :children } }, :order => 'mixins.id')
279
+ assert_equal @rc4, assert_no_queries { root_node.children.first.children.first.children.first }
280
+ end
281
+
282
+ def test_eager_association_loading_with_recursive_cascading_three_levels_has_one
283
+ root_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :first_child => { :first_child => :first_child } }, :order => 'mixins.id')
284
+ assert_equal @rc4, assert_no_queries { root_node.first_child.first_child.first_child }
285
+ end
286
+
287
+ def test_eager_association_loading_with_recursive_cascading_three_levels_belongs_to
288
+ leaf_node = RecursivelyCascadedTreeMixin.find(:first, :include => { :parent => { :parent => :parent } }, :order => 'mixins.id DESC')
289
+ assert_equal @rc1, assert_no_queries { leaf_node.parent.parent.parent }
290
+ end
291
+ end
292
+
293
+ class TreeTestWithoutOrder < Test::Unit::TestCase
294
+ def setup
295
+ setup_db
296
+ @root1 = TreeMixinWithoutOrder.create!
297
+ @root2 = TreeMixinWithoutOrder.create!
298
+ end
299
+
300
+ def teardown
301
+ teardown_db
302
+ end
303
+
304
+ def test_root
305
+ assert [@root1, @root2].include?(TreeMixinWithoutOrder.root)
306
+ end
307
+
308
+ def test_roots
309
+ assert_equal [], [@root1, @root2] - TreeMixinWithoutOrder.roots
310
+ end
311
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parndt-acts_as_tree
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 2
9
+ - 5
10
+ version: 1.2.5
11
+ platform: ruby
12
+ authors:
13
+ - David Heinemeier Hansson
14
+ - Philip Arndt
15
+ - Others
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2010-08-31 00:00:00 +12:00
21
+ default_executable:
22
+ dependencies: []
23
+
24
+ description: |-
25
+ Use this acts_as extension if you want to model a tree structure by providing a parent association and a children
26
+ association.
27
+ email:
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - init.rb
36
+ - lib/active_record/acts/tree.rb
37
+ - lib/acts_as_tree.rb
38
+ - lib/gemspec.rb
39
+ - rails/init.rb
40
+ - Rakefile
41
+ - readme.textile
42
+ - test/acts_as_tree_test.rb
43
+ - VERSION
44
+ has_rdoc: true
45
+ homepage: http://philiparndt.name
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 0
61
+ version: "0"
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ hash: 3
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ requirements: []
72
+
73
+ rubyforge_project:
74
+ rubygems_version: 1.3.7
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: acts_as_tree plugin.
78
+ test_files:
79
+ - test/acts_as_tree_test.rb