closure_tree 3.0.1 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -197,6 +197,10 @@ class WhatTag < Tag ; end
197
197
 
198
198
  * Support 3.2.0's fickle deprecation of InstanceMethods (Thanks, [jheiss](https://github.com/mceachen/closure_tree/pull/5))!
199
199
 
200
+ ### 3.0.2
201
+
202
+ * Fix for ancestry-loop detection (performed by a validation, not through raising an exception in before_save)
203
+
200
204
  ## Thanks to
201
205
 
202
206
  * https://github.com/collectiveidea/awesome_nested_set
@@ -27,9 +27,10 @@ module ClosureTree
27
27
 
28
28
  include ClosureTree::Model
29
29
 
30
- before_destroy :acts_as_tree_before_destroy
30
+ validate :acts_as_tree_validate
31
31
  before_save :acts_as_tree_before_save
32
32
  after_save :acts_as_tree_after_save
33
+ before_destroy :acts_as_tree_before_destroy
33
34
 
34
35
  belongs_to :parent,
35
36
  :class_name => ct_class.to_s,
@@ -162,16 +163,19 @@ module ClosureTree
162
163
 
163
164
  protected
164
165
 
165
- def acts_as_tree_before_save
166
- @was_new_record = new_record?
166
+ def acts_as_tree_validate
167
167
  if changes[parent_column_name] &&
168
168
  parent.present? &&
169
169
  parent.self_and_ancestors.include?(self)
170
- # TODO: raise Ouroboros or Philip J. Fry error:
171
- raise ActiveRecord::ActiveRecordError "You cannot add an ancestor as a descendant"
170
+ errors.add(parent_column_sym, "You cannot add an ancestor as a descendant")
172
171
  end
173
172
  end
174
173
 
174
+ def acts_as_tree_before_save
175
+ @was_new_record = new_record?
176
+ nil # AR will cancel the save if this is falsy
177
+ end
178
+
175
179
  def acts_as_tree_after_save
176
180
  rebuild! if changes[parent_column_name] || @was_new_record
177
181
  end
@@ -1,3 +1,3 @@
1
1
  module ClosureTree
2
- VERSION = "3.0.1" unless defined?(::ClosureTree::VERSION)
2
+ VERSION = "3.0.2" unless defined?(::ClosureTree::VERSION)
3
3
  end
@@ -83,16 +83,18 @@ describe "empty db" do
83
83
  Tag.leaves.should == [@leaf]
84
84
  end
85
85
 
86
- it "should prevent parental loops" do
87
- lambda do
88
- @mid.children << @root
89
- end.should raise_error
90
-
91
- lambda do
92
- @leaf.children << @root
93
- end.should raise_error
86
+ it "should prevent parental loops from torso" do
87
+ @mid.children << @root
88
+ @root.valid?.should be_false
89
+ @mid.reload.children.should == [@leaf]
94
90
  end
95
91
 
92
+ it "should prevent parental loops from toes" do
93
+ @leaf.children << @root
94
+ @root.valid?.should be_false
95
+ @leaf.reload.children.should be_empty
96
+ end
97
+
96
98
  it "should support reparenting" do
97
99
  @root.children << @leaf
98
100
  Tag.leaves.should =~ [@leaf, @mid]
@@ -168,9 +170,12 @@ describe Tag do
168
170
  end
169
171
 
170
172
  it "should fail to create ancestor loops" do
171
- lambda do
172
- tags(:child).add_child(tags(:grandparent))
173
- end.should raise_error
173
+ child = tags(:child)
174
+ parent = child.parent
175
+ child.add_child(parent) # this should fail
176
+ parent.valid?.should be_false
177
+ child.reload.children.should be_empty
178
+ parent.reload.children.should =~ [child]
174
179
  end
175
180
 
176
181
  it "should move non-leaves" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: closure_tree
3
3
  version: !ruby/object:Gem::Version
4
- hash: 5
4
+ hash: 3
5
5
  prerelease:
6
6
  segments:
7
7
  - 3
8
8
  - 0
9
- - 1
10
- version: 3.0.1
9
+ - 2
10
+ version: 3.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Matthew McEachen
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-30 00:00:00 Z
18
+ date: 2012-02-07 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  prerelease: false