closure_tree 3.7.1 → 3.7.2

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.
data/README.md CHANGED
@@ -396,6 +396,12 @@ Parallelism is not tested with Rails 3.0.x nor 3.1.x due to this
396
396
 
397
397
  ## Change log
398
398
 
399
+ ### 3.7.2
400
+
401
+ * Support for UUID primary keys. Addresses
402
+ [issue 40](https://github.com/mceachen/closure_tree/issues/40). Thanks for the pull request,
403
+ [Julien](https://github.com/calexicoz)!
404
+
399
405
  ### 3.7.1
400
406
 
401
407
  * Moved requires into ActiveSupport.on_load
@@ -550,4 +556,3 @@ a.save
550
556
  * https://github.com/patshaughnessy/class_factory
551
557
  * JetBrains, which provides an [open-source license](http://www.jetbrains.com/ruby/buy/buy.jsp#openSource) to
552
558
  [RubyMine](http://www.jetbrains.com/ruby/features/) for the development of this project.
553
-
@@ -237,7 +237,7 @@ module ClosureTree
237
237
  INNER JOIN (
238
238
  SELECT descendant_id
239
239
  FROM #{quoted_hierarchy_table_name}
240
- WHERE ancestor_id = #{self.id}
240
+ WHERE ancestor_id = #{ct_quote(self.id)}
241
241
  GROUP BY 1
242
242
  HAVING MAX(#{quoted_hierarchy_table_name}.generations) = #{generation_level.to_i}
243
243
  ) AS descendants ON (#{quoted_table_name}.#{ct_base_class.primary_key} = descendants.descendant_id)
@@ -290,9 +290,9 @@ module ClosureTree
290
290
  connection.execute <<-SQL
291
291
  INSERT INTO #{quoted_hierarchy_table_name}
292
292
  (ancestor_id, descendant_id, generations)
293
- SELECT x.ancestor_id, #{id}, x.generations + 1
293
+ SELECT x.ancestor_id, #{ct_quote(id)}, x.generations + 1
294
294
  FROM #{quoted_hierarchy_table_name} x
295
- WHERE x.descendant_id = #{self.ct_parent_id}
295
+ WHERE x.descendant_id = #{ct_quote(self.ct_parent_id)}
296
296
  SQL
297
297
  end
298
298
  children.each { |c| c.rebuild! }
@@ -316,9 +316,9 @@ module ClosureTree
316
316
  SELECT DISTINCT descendant_id
317
317
  FROM ( SELECT descendant_id
318
318
  FROM #{quoted_hierarchy_table_name}
319
- WHERE ancestor_id = #{id}
319
+ WHERE ancestor_id = #{ct_quote(id)}
320
320
  ) AS x )
321
- OR descendant_id = #{id}
321
+ OR descendant_id = #{ct_quote(id)}
322
322
  SQL
323
323
  end
324
324
 
@@ -334,6 +334,10 @@ module ClosureTree
334
334
  end
335
335
  end
336
336
 
337
+ def ct_quote(field)
338
+ self.class.connection.quote(field)
339
+ end
340
+
337
341
  # TODO: _parent_id will be removed in the next major version
338
342
  alias :_parent_id :ct_parent_id
339
343
 
@@ -1,3 +1,3 @@
1
1
  module ClosureTree
2
- VERSION = "3.7.1" unless defined?(::ClosureTree::VERSION)
2
+ VERSION = "3.7.2" unless defined?(::ClosureTree::VERSION)
3
3
  end
data/spec/db/schema.rb CHANGED
@@ -11,6 +11,22 @@ end
11
11
 
12
12
  ActiveRecord::Schema.define(:version => 0) do
13
13
 
14
+ create_table "nodes", :id => false do |t|
15
+ t.string "id"
16
+ t.string "name"
17
+ t.string "parent_id"
18
+ t.datetime "created_at"
19
+ t.datetime "updated_at"
20
+ end
21
+
22
+ force_add_index "nodes", [:id], :name => "node_id", :unique => true
23
+
24
+ create_table "node_hierarchies", :id => false, :force => true do |t|
25
+ t.string "ancestor_id", :null => false
26
+ t.string "descendant_id", :null => false
27
+ t.integer "generations", :null => false
28
+ end
29
+
14
30
  create_table "tags", :force => true do |t|
15
31
  t.string "name"
16
32
  t.string "title"
data/spec/node_spec.rb ADDED
@@ -0,0 +1,148 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples_for Node do
4
+
5
+ it "has correct accessible_attributes" do
6
+ Node.accessible_attributes.to_a.should =~ %w(parent name)
7
+ end
8
+
9
+ describe "empty db" do
10
+
11
+ def nuke_db
12
+ NodeHierarchy.delete_all
13
+ Node.delete_all
14
+ end
15
+
16
+ before :each do
17
+ nuke_db
18
+ end
19
+
20
+ context "empty db" do
21
+ it "should return no entities" do
22
+ Node.roots.should be_empty
23
+ Node.leaves.should be_empty
24
+ end
25
+ end
26
+
27
+ context "1 node db" do
28
+ it "should return the only entity as a root and leaf" do
29
+ a = Node.create!(:name => "a")
30
+ Node.roots.should == [a]
31
+ Node.leaves.should == [a]
32
+ end
33
+ end
34
+
35
+ context "2 node db" do
36
+ it "should return a simple root and leaf" do
37
+ root = Node.create!(:name => "root")
38
+ leaf = root.add_child(Node.create!(:name => "leaf"))
39
+ Node.roots.should == [root]
40
+ Node.leaves.should == [leaf]
41
+ end
42
+ end
43
+
44
+ context "3 node collection.create db" do
45
+ before :each do
46
+ @root = Node.create! :name => "root"
47
+ @mid = @root.children.create! :name => "mid"
48
+ @leaf = @mid.children.create! :name => "leaf"
49
+ end
50
+
51
+ it "should create all nodes" do
52
+ Node.all.should =~ [@root, @mid, @leaf]
53
+ end
54
+
55
+ it "should return a root and leaf without middle node" do
56
+ Node.roots.should == [@root]
57
+ Node.leaves.should == [@leaf]
58
+ end
59
+
60
+ it "should delete leaves" do
61
+ Node.leaves.destroy_all
62
+ Node.roots.should == [@root] # untouched
63
+ Node.leaves.should == [@mid]
64
+ end
65
+
66
+ it "should delete everything if you delete the roots" do
67
+ Node.roots.destroy_all
68
+ Node.all.should be_empty
69
+ Node.roots.should be_empty
70
+ Node.leaves.should be_empty
71
+ end
72
+ end
73
+
74
+ context "3 node explicit_create db" do
75
+ before :each do
76
+ @root = Node.create!(:name => "root")
77
+ @mid = @root.add_child(Node.create!(:name => "mid"))
78
+ @leaf = @mid.add_child(Node.create!(:name => "leaf"))
79
+ end
80
+
81
+ it "should create all nodes" do
82
+ Node.all.should =~ [@root, @mid, @leaf]
83
+ end
84
+
85
+ it "should return a root and leaf without middle node" do
86
+ Node.roots.should == [@root]
87
+ Node.leaves.should == [@leaf]
88
+ end
89
+
90
+ it "should prevent parental loops from torso" do
91
+ @mid.children << @root
92
+ @root.valid?.should be_false
93
+ @mid.reload.children.should == [@leaf]
94
+ end
95
+
96
+ it "should prevent parental loops from toes" do
97
+ @leaf.children << @root
98
+ @root.valid?.should be_false
99
+ @leaf.reload.children.should be_empty
100
+ end
101
+
102
+ it "should support re-parenting" do
103
+ @root.children << @leaf
104
+ Node.leaves.should =~ [@leaf, @mid]
105
+ end
106
+
107
+ it "cleans up hierarchy references for leaves" do
108
+ @leaf.destroy
109
+ NodeHierarchy.find_all_by_ancestor_id(@leaf.id).should be_empty
110
+ NodeHierarchy.find_all_by_descendant_id(@leaf.id).should be_empty
111
+ end
112
+
113
+ it "cleans up hierarchy references" do
114
+ @mid.destroy
115
+ NodeHierarchy.find_all_by_ancestor_id(@mid.id).should be_empty
116
+ NodeHierarchy.find_all_by_descendant_id(@mid.id).should be_empty
117
+ @root.reload.should be_root
118
+ root_hiers = @root.ancestor_hierarchies.to_a
119
+ root_hiers.size.should == 1
120
+ NodeHierarchy.find_all_by_ancestor_id(@root.id).should == root_hiers
121
+ NodeHierarchy.find_all_by_descendant_id(@root.id).should == root_hiers
122
+ end
123
+ end
124
+
125
+ it "performs as the readme says it does" do
126
+ grandparent = Node.create(:name => 'Grandparent')
127
+ parent = grandparent.children.create(:name => 'Parent')
128
+ child1 = Node.create(:name => 'First Child', :parent => parent)
129
+ child2 = Node.new(:name => 'Second Child')
130
+ parent.children << child2
131
+ child3 = Node.new(:name => 'Third Child')
132
+ parent.add_child child3
133
+ grandparent.self_and_descendants.collect(&:name).should ==
134
+ ["Grandparent", "Parent", "First Child", "Second Child", "Third Child"]
135
+ child1.ancestry_path.should ==
136
+ ["Grandparent", "Parent", "First Child"]
137
+ child3.ancestry_path.should ==
138
+ ["Grandparent", "Parent", "Third Child"]
139
+ d = Node.find_or_create_by_path %w(a b c d)
140
+ h = Node.find_or_create_by_path %w(e f g h)
141
+ e = h.root
142
+ d.add_child(e) # "d.children << e" would work too, of course
143
+ h.ancestry_path.should == %w(a b c d e f g h)
144
+ end
145
+
146
+ end
147
+
148
+ end
@@ -1,3 +1,15 @@
1
+ require 'uuidtools'
2
+
3
+ class Node < ActiveRecord::Base
4
+ acts_as_tree :dependent => :destroy
5
+ before_create :generate_uuid
6
+ attr_accessible :name
7
+
8
+ def generate_uuid
9
+ self.id = UUIDTools::UUID.random_create.to_s
10
+ end
11
+ end
12
+
1
13
  class Tag < ActiveRecord::Base
2
14
  acts_as_tree :dependent => :destroy, :order => "name"
3
15
  before_destroy :add_destroyed_tag
@@ -60,4 +72,4 @@ end
60
72
 
61
73
  class CuisineType < ActiveRecord::Base
62
74
  acts_as_tree
63
- end
75
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: closure_tree
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.7.1
4
+ version: 3.7.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-26 00:00:00.000000000 Z
12
+ date: 2013-02-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -171,6 +171,22 @@ dependencies:
171
171
  - - ! '>='
172
172
  - !ruby/object:Gem::Version
173
173
  version: '0'
174
+ - !ruby/object:Gem::Dependency
175
+ name: uuidtools
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
174
190
  - !ruby/object:Gem::Dependency
175
191
  name: strong_parameters
176
192
  requirement: !ruby/object:Gem::Requirement
@@ -207,6 +223,7 @@ files:
207
223
  - spec/fixtures/tags.yml
208
224
  - spec/hash_tree_spec.rb
209
225
  - spec/label_spec.rb
226
+ - spec/node_spec.rb
210
227
  - spec/parallel_spec.rb
211
228
  - spec/spec_helper.rb
212
229
  - spec/support/models.rb
@@ -226,7 +243,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
226
243
  version: '0'
227
244
  segments:
228
245
  - 0
229
- hash: -469383754744352322
246
+ hash: -2260215237559696293
230
247
  required_rubygems_version: !ruby/object:Gem::Requirement
231
248
  none: false
232
249
  requirements:
@@ -235,7 +252,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
252
  version: '0'
236
253
  segments:
237
254
  - 0
238
- hash: -469383754744352322
255
+ hash: -2260215237559696293
239
256
  requirements: []
240
257
  rubyforge_project:
241
258
  rubygems_version: 1.8.23
@@ -250,6 +267,7 @@ test_files:
250
267
  - spec/fixtures/tags.yml
251
268
  - spec/hash_tree_spec.rb
252
269
  - spec/label_spec.rb
270
+ - spec/node_spec.rb
253
271
  - spec/parallel_spec.rb
254
272
  - spec/spec_helper.rb
255
273
  - spec/support/models.rb