dm-is-awesome_set 0.11.1 → 1.0.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.
- data/.gitignore +2 -0
- data/Gemfile +20 -0
- data/Rakefile +4 -6
- data/VERSION +1 -1
- data/dm-is-awesome_set.gemspec +17 -13
- data/lib/dm-is-awesome_set.rb +44 -21
- data/spec/dm-is-awesome_set_spec.rb +319 -1
- data/spec/spec_helper.rb +22 -2
- data/tasks/spec.rake +0 -3
- metadata +72 -23
data/.gitignore
CHANGED
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
gem 'activesupport', '~> 3.0.0.beta3', :git => 'git://github.com/rails/rails.git', :require => 'active_support'
|
4
|
+
|
5
|
+
gem 'dm-core', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-core.git'
|
6
|
+
gem 'dm-transactions', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-transactions.git'
|
7
|
+
gem 'dm-migrations', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-migrations.git'
|
8
|
+
gem 'dm-types', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-types.git'
|
9
|
+
gem 'dm-validations', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-validations.git'
|
10
|
+
gem 'dm-adjust', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-adjust.git'
|
11
|
+
gem 'dm-aggregates', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-aggregates.git'
|
12
|
+
|
13
|
+
gem 'dm-do-adapter', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-do-adapter.git'
|
14
|
+
gem 'dm-sqlite-adapter', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-sqlite-adapter.git'
|
15
|
+
gem 'dm-mysql-adapter', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-mysql-adapter.git'
|
16
|
+
# gem 'dm-postgres-adapter', '~> 1.0.0', :git => 'git://github.com/datamapper/dm-postgres-adapter.git'
|
17
|
+
|
18
|
+
gem 'rake', '~> 0.8.7'
|
19
|
+
gem 'jeweler', '~> 1.4'
|
20
|
+
gem 'rspec', '~> 1.3'
|
data/Rakefile
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'rake'
|
3
2
|
|
4
3
|
begin
|
5
4
|
|
6
|
-
gem 'jeweler', '>= 1.4'
|
7
5
|
require 'jeweler'
|
8
6
|
|
9
7
|
FileList['tasks/**/*.rake'].each { |task| load task }
|
@@ -17,9 +15,10 @@ begin
|
|
17
15
|
gem.homepage = "http://github.com/snusnu/dm-is-awesome_set"
|
18
16
|
gem.authors = ["Jeremy Nicoll", "David Haslem", "Martin Gamsjaeger (snusnu)"]
|
19
17
|
|
20
|
-
gem.add_dependency 'dm-core', '~> 0
|
21
|
-
gem.add_dependency 'dm-adjust', '~> 0
|
22
|
-
gem.add_dependency 'dm-aggregates', '~> 0
|
18
|
+
gem.add_dependency 'dm-core', '~> 1.0'
|
19
|
+
gem.add_dependency 'dm-adjust', '~> 1.0'
|
20
|
+
gem.add_dependency 'dm-aggregates', '~> 1.0'
|
21
|
+
gem.add_dependency 'dm-transactions', '~> 1.0'
|
23
22
|
|
24
23
|
gem.add_development_dependency 'rspec', '~> 1.2.9'
|
25
24
|
|
@@ -31,5 +30,4 @@ rescue LoadError
|
|
31
30
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
32
31
|
end
|
33
32
|
|
34
|
-
task :spec => :check_dependencies
|
35
33
|
task :default => :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.1
|
data/dm-is-awesome_set.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dm-is-awesome_set}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "1.0.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeremy Nicoll", "David Haslem", "Martin Gamsjaeger (snusnu)"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-07-09}
|
13
13
|
s.description = %q{A library that lets any datamapper model act like a nested set}
|
14
14
|
s.email = %q{jnicoll@gnexp.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
]
|
20
20
|
s.files = [
|
21
21
|
".gitignore",
|
22
|
+
"Gemfile",
|
22
23
|
"LICENSE",
|
23
24
|
"README",
|
24
25
|
"Rakefile",
|
@@ -40,7 +41,7 @@ Gem::Specification.new do |s|
|
|
40
41
|
s.homepage = %q{http://github.com/snusnu/dm-is-awesome_set}
|
41
42
|
s.rdoc_options = ["--charset=UTF-8"]
|
42
43
|
s.require_paths = ["lib"]
|
43
|
-
s.rubygems_version = %q{1.3.
|
44
|
+
s.rubygems_version = %q{1.3.7}
|
44
45
|
s.summary = %q{A nested set plugin for datamapper}
|
45
46
|
s.test_files = [
|
46
47
|
"spec/dm-is-awesome_set_spec.rb",
|
@@ -51,21 +52,24 @@ Gem::Specification.new do |s|
|
|
51
52
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
52
53
|
s.specification_version = 3
|
53
54
|
|
54
|
-
if Gem::Version.new(Gem::
|
55
|
-
s.add_runtime_dependency(%q<dm-core>, ["~> 0
|
56
|
-
s.add_runtime_dependency(%q<dm-adjust>, ["~> 0
|
57
|
-
s.add_runtime_dependency(%q<dm-aggregates>, ["~> 0
|
55
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
56
|
+
s.add_runtime_dependency(%q<dm-core>, ["~> 1.0"])
|
57
|
+
s.add_runtime_dependency(%q<dm-adjust>, ["~> 1.0"])
|
58
|
+
s.add_runtime_dependency(%q<dm-aggregates>, ["~> 1.0"])
|
59
|
+
s.add_runtime_dependency(%q<dm-transactions>, ["~> 1.0"])
|
58
60
|
s.add_development_dependency(%q<rspec>, ["~> 1.2.9"])
|
59
61
|
else
|
60
|
-
s.add_dependency(%q<dm-core>, ["~> 0
|
61
|
-
s.add_dependency(%q<dm-adjust>, ["~> 0
|
62
|
-
s.add_dependency(%q<dm-aggregates>, ["~> 0
|
62
|
+
s.add_dependency(%q<dm-core>, ["~> 1.0"])
|
63
|
+
s.add_dependency(%q<dm-adjust>, ["~> 1.0"])
|
64
|
+
s.add_dependency(%q<dm-aggregates>, ["~> 1.0"])
|
65
|
+
s.add_dependency(%q<dm-transactions>, ["~> 1.0"])
|
63
66
|
s.add_dependency(%q<rspec>, ["~> 1.2.9"])
|
64
67
|
end
|
65
68
|
else
|
66
|
-
s.add_dependency(%q<dm-core>, ["~> 0
|
67
|
-
s.add_dependency(%q<dm-adjust>, ["~> 0
|
68
|
-
s.add_dependency(%q<dm-aggregates>, ["~> 0
|
69
|
+
s.add_dependency(%q<dm-core>, ["~> 1.0"])
|
70
|
+
s.add_dependency(%q<dm-adjust>, ["~> 1.0"])
|
71
|
+
s.add_dependency(%q<dm-aggregates>, ["~> 1.0"])
|
72
|
+
s.add_dependency(%q<dm-transactions>, ["~> 1.0"])
|
69
73
|
s.add_dependency(%q<rspec>, ["~> 1.2.9"])
|
70
74
|
end
|
71
75
|
end
|
data/lib/dm-is-awesome_set.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
['dm-core', 'dm-adjust', 'dm-aggregates', 'dm-
|
1
|
+
['dm-core', 'dm-adjust', 'dm-aggregates', 'dm-transactions'].each do |dm_var|
|
2
2
|
require dm_var
|
3
3
|
end
|
4
4
|
|
@@ -28,7 +28,7 @@ module DataMapper
|
|
28
28
|
def is_awesome_set(options={})
|
29
29
|
extend DataMapper::Is::AwesomeSet::ClassMethods
|
30
30
|
include DataMapper::Is::AwesomeSet::InstanceMethods
|
31
|
-
|
31
|
+
|
32
32
|
opts = set_options(options)
|
33
33
|
[:child_key, :scope].each {|var| raise "#{var} must be an Array" unless opts[var].is_a?(Array)}
|
34
34
|
|
@@ -41,7 +41,7 @@ module DataMapper
|
|
41
41
|
belongs_to :parent, class_opts
|
42
42
|
has n, :children, class_opts
|
43
43
|
|
44
|
-
before :
|
44
|
+
before :save do
|
45
45
|
move_without_saving(:root) if lft.nil? #You don't want to use new_record? here. Trust me, you don't.
|
46
46
|
end
|
47
47
|
|
@@ -78,7 +78,14 @@ module DataMapper
|
|
78
78
|
check_scope(hash)
|
79
79
|
ret = {}
|
80
80
|
send_to_obj = hash.is_a?(self)
|
81
|
-
|
81
|
+
|
82
|
+
scope_keys.each do |sk|
|
83
|
+
if send_to_obj && self.public_method_defined?(name = sk)
|
84
|
+
ret[sk] = hash.__send__(sk)
|
85
|
+
else
|
86
|
+
ret[sk] = hash[sk]
|
87
|
+
end
|
88
|
+
end
|
82
89
|
ret
|
83
90
|
end
|
84
91
|
|
@@ -157,7 +164,7 @@ module DataMapper
|
|
157
164
|
# @see move_without_saving
|
158
165
|
|
159
166
|
def move(vector)
|
160
|
-
transaction do
|
167
|
+
get_class.transaction do
|
161
168
|
move_without_saving(vector)
|
162
169
|
save!
|
163
170
|
end
|
@@ -218,12 +225,26 @@ module DataMapper
|
|
218
225
|
get_class.all(scope_hash.merge(:rgt.lt => rgt, :lft.gt => lft, :order => [:lft.asc]))
|
219
226
|
end
|
220
227
|
|
221
|
-
|
222
228
|
# Same as descendents, but returns self as well
|
223
229
|
def self_and_descendents
|
224
230
|
get_class.all(scope_hash.merge(:rgt.lte => rgt, :lft.gte => lft, :order => [:lft.asc]))
|
225
231
|
end
|
226
232
|
|
233
|
+
def descendant?(ancestor)
|
234
|
+
ancestor.lft < lft && ancestor.rgt > rgt
|
235
|
+
end
|
236
|
+
|
237
|
+
def self_or_descendant?(ancestor)
|
238
|
+
ancestor.lft <= lft && ancestor.rgt >= rgt
|
239
|
+
end
|
240
|
+
|
241
|
+
def ancestor?(descendant)
|
242
|
+
descendant.lft > lft && descendant.rgt < rgt
|
243
|
+
end
|
244
|
+
|
245
|
+
def self_or_ancestor?(descendant)
|
246
|
+
descendant.lft >= lft && descendant.rgt <= rgt
|
247
|
+
end
|
227
248
|
|
228
249
|
# Fixed spelling for when English majors are peering over your shoulder
|
229
250
|
def descendants; descendents; end
|
@@ -236,35 +257,37 @@ module DataMapper
|
|
236
257
|
|
237
258
|
def attributes_set(hash) #:nodoc:
|
238
259
|
hash = hash || {}
|
239
|
-
|
260
|
+
self.attributes = hash
|
240
261
|
end
|
241
262
|
|
242
263
|
# Destroys the current node and all children nodes, running their before and after hooks
|
243
264
|
# Returns the destroyed objects
|
244
265
|
def destroy
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
266
|
+
return true if destroyed?
|
267
|
+
catch :halt do
|
268
|
+
sads = self_and_descendants
|
269
|
+
# Trigger all the before :destroy methods
|
270
|
+
sads.each { |sad| sad.before_destroy_hook }
|
271
|
+
# dup is called here because destroy! likes to clear out the array, understandably.
|
272
|
+
get_class.transaction do
|
273
|
+
sads.dup.destroy!
|
274
|
+
adjust_gap!(full_set, lft, -(rgt - lft + 1))
|
275
|
+
end
|
276
|
+
# Now go through after all the after :destroy methods.
|
277
|
+
sads.each { |sad| sad.after_destroy_hook }
|
255
278
|
end
|
256
|
-
|
257
|
-
sads.each { |sad| after_methods.each { |bf| sad.send(bf) } }
|
279
|
+
destroyed?
|
258
280
|
end
|
259
281
|
|
260
282
|
# Same as @destroy, but does not run the hooks
|
261
283
|
def destroy!
|
284
|
+
return true if destroyed?
|
262
285
|
sad = self_and_descendants
|
263
|
-
transaction do
|
286
|
+
get_class.transaction do
|
264
287
|
sad.dup.destroy!
|
265
288
|
adjust_gap!(full_set, lft, -(rgt - lft + 1))
|
266
289
|
end
|
267
|
-
|
290
|
+
destroyed?
|
268
291
|
end
|
269
292
|
|
270
293
|
protected
|
@@ -16,6 +16,8 @@ describe DataMapper::Is::AwesomeSet do
|
|
16
16
|
Category.auto_migrate!
|
17
17
|
Discrim1.auto_migrate!
|
18
18
|
Discrim2.auto_migrate!
|
19
|
+
FileServer.auto_migrate!
|
20
|
+
FileServerItem.auto_migrate!
|
19
21
|
end
|
20
22
|
|
21
23
|
it "puts itself as the last root in the defined scope on initial save" do
|
@@ -30,6 +32,17 @@ describe DataMapper::Is::AwesomeSet do
|
|
30
32
|
c3.pos.should eql([1,2])
|
31
33
|
c4.pos.should eql([3,4])
|
32
34
|
|
35
|
+
s1 = FileServer.create({:name => 'foo'})
|
36
|
+
s2 = FileServer.create({:name => 'bar'})
|
37
|
+
f1 = FileServerItem.create({:file_server => s1})
|
38
|
+
f2 = FileServerItem.create({:file_server => s1})
|
39
|
+
f1.pos.should eql([1,2])
|
40
|
+
f2.pos.should eql([3,4])
|
41
|
+
|
42
|
+
f3 = FileServerItem.create({:file_server => s2})
|
43
|
+
f4 = FileServerItem.create({:file_server => s2})
|
44
|
+
f3.pos.should eql([1,2])
|
45
|
+
f4.pos.should eql([3,4])
|
33
46
|
end
|
34
47
|
|
35
48
|
it "moves itself into a parent" do
|
@@ -51,7 +64,8 @@ describe DataMapper::Is::AwesomeSet do
|
|
51
64
|
c3.pos.should eql([3,6])
|
52
65
|
c2.pos.should eql([4,5])
|
53
66
|
|
54
|
-
# This is to ensure that
|
67
|
+
# This section is to ensure that scope updates
|
68
|
+
# when moving into a parent with different scope
|
55
69
|
c4 = Category.new
|
56
70
|
c4.move(:into => c1)
|
57
71
|
[c1,c2,c3, c4].each { |c| c.reload }
|
@@ -61,6 +75,16 @@ describe DataMapper::Is::AwesomeSet do
|
|
61
75
|
c3.pos.should eql([5,8])
|
62
76
|
c2.pos.should eql([6,7])
|
63
77
|
end
|
78
|
+
|
79
|
+
it "moves itself into a parent with relationship scope update" do
|
80
|
+
s1 = FileServer.create({:name => 'foo'})
|
81
|
+
f1 = FileServerItem.create({:file_server => s1})
|
82
|
+
f2 = FileServerItem.new
|
83
|
+
f2.sco.should_not eql(f1.sco)
|
84
|
+
f2.move(:into => f1)
|
85
|
+
[f1, f2].each { |f| f.reload }
|
86
|
+
f2.sco.should eql(f1.sco)
|
87
|
+
end
|
64
88
|
|
65
89
|
it "moves around properly" do
|
66
90
|
c1 = Category.create(scope)
|
@@ -185,9 +209,26 @@ describe DataMapper::Is::AwesomeSet do
|
|
185
209
|
c3 = Category.create(scope)
|
186
210
|
c2.move :into => c1
|
187
211
|
c3.move :into => c2
|
212
|
+
c2.root.should_not be_nil
|
213
|
+
c2.root.id.should eql(c1.id)
|
188
214
|
c3.root.should_not be_nil
|
189
215
|
c3.root.id.should eql(c1.id)
|
190
216
|
end
|
217
|
+
|
218
|
+
it "identifies the root with relationship scopes" do
|
219
|
+
# Root with relationship scope
|
220
|
+
s1 = FileServer.create({:name => 'foo'})
|
221
|
+
f1 = FileServerItem.create({:file_server => s1})
|
222
|
+
f2 = FileServerItem.create({:file_server => s1})
|
223
|
+
f3 = FileServerItem.create({:file_server => s1})
|
224
|
+
f2.move(:into => f1)
|
225
|
+
f3.move(:into => f2)
|
226
|
+
f2.root.should_not be_nil
|
227
|
+
f2.root.id.should eql(f1.id)
|
228
|
+
f3.root.should_not be_nil
|
229
|
+
f3.root.id.should eql(f1.id)
|
230
|
+
|
231
|
+
end
|
191
232
|
|
192
233
|
it "gets all roots in the current scope" do
|
193
234
|
c1 = Category.create(scope)
|
@@ -197,6 +238,18 @@ describe DataMapper::Is::AwesomeSet do
|
|
197
238
|
c3 = Category.create(scope2)
|
198
239
|
c4 = Category.create(scope2)
|
199
240
|
c3.roots.size.should eql(2)
|
241
|
+
|
242
|
+
# All roots for scope if relationship in scope
|
243
|
+
s1 = FileServer.create({:name => 'foo'})
|
244
|
+
f1 = FileServerItem.create({:file_server => s1})
|
245
|
+
f2 = FileServerItem.create({:file_server => s1})
|
246
|
+
f2.roots.size.should eql(2)
|
247
|
+
|
248
|
+
s2 = FileServer.create({:name => 'bar'})
|
249
|
+
f3 = FileServerItem.create({:file_server => s2})
|
250
|
+
f4 = FileServerItem.create({:file_server => s2})
|
251
|
+
f3.roots.size.should eql(2)
|
252
|
+
|
200
253
|
end
|
201
254
|
|
202
255
|
it "gets all ancestors" do
|
@@ -292,7 +345,62 @@ describe DataMapper::Is::AwesomeSet do
|
|
292
345
|
c5.pos.should eql([9,10])
|
293
346
|
|
294
347
|
c6.pos.should eql([1,2])
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
it "moves scope properly with relationships" do
|
352
|
+
# Relationship scope tests
|
353
|
+
s1 = FileServer.create({:name => 'foo'})
|
354
|
+
server1 = {:file_server => s1}
|
355
|
+
f1 = FileServerItem.create({:file_server => s1})
|
356
|
+
f2 = FileServerItem.create({:file_server => s1})
|
357
|
+
f3 = FileServerItem.create({:file_server => s1})
|
358
|
+
|
359
|
+
s2 = FileServer.create({:name => 'bar'})
|
360
|
+
server2 = {:file_server => s2}
|
361
|
+
f4 = FileServerItem.create({:file_server => s2})
|
362
|
+
f5 = FileServerItem.create({:file_server => s2})
|
363
|
+
f6 = FileServerItem.create({:file_server => s2})
|
364
|
+
|
365
|
+
f1.move(:into => f4)
|
366
|
+
[f1,f2,f3,f4,f5,f6].each { |c| c.reload }
|
367
|
+
f1.sco.should eql(server2)
|
368
|
+
|
369
|
+
f2.pos.should eql([1,2])
|
370
|
+
f3.pos.should eql([3,4])
|
371
|
+
|
372
|
+
f4.pos.should eql([1,4])
|
373
|
+
f1.pos.should eql([2,3])
|
374
|
+
f5.pos.should eql([5,6])
|
375
|
+
f6.pos.should eql([7,8])
|
376
|
+
|
377
|
+
f4.move(:into => f2)
|
378
|
+
[f1,f2,f3,f4,f5,f6].each { |c| c.reload }
|
379
|
+
f1.sco.should eql(server1)
|
380
|
+
f4.sco.should eql(server1)
|
381
|
+
|
382
|
+
f2.pos.should eql([1,6])
|
383
|
+
f4.pos.should eql([2,5])
|
384
|
+
f1.pos.should eql([3,4])
|
385
|
+
f3.pos.should eql([7,8])
|
386
|
+
|
295
387
|
|
388
|
+
f5.pos.should eql([1,2])
|
389
|
+
f6.pos.should eql([3,4])
|
390
|
+
|
391
|
+
# You can move into the root of a different scope by passing an object from that scope
|
392
|
+
# or a hash that represents that scope
|
393
|
+
f5.move(:root => server1)
|
394
|
+
[f1,f2,f3,f4,f5,f6].each { |c| c.reload }
|
395
|
+
f5.sco.should eql(server1)
|
396
|
+
|
397
|
+
f2.pos.should eql([1,6])
|
398
|
+
f4.pos.should eql([2,5])
|
399
|
+
f1.pos.should eql([3,4])
|
400
|
+
f3.pos.should eql([7,8])
|
401
|
+
f5.pos.should eql([9,10])
|
402
|
+
|
403
|
+
f6.pos.should eql([1,2])
|
296
404
|
end
|
297
405
|
|
298
406
|
it "should get all rows in the database if the discrimator is not part of scope" do
|
@@ -312,6 +420,66 @@ describe DataMapper::Is::AwesomeSet do
|
|
312
420
|
Discrim2.roots(scope2.merge(:type => 'CatD22')).size.should eql(2)
|
313
421
|
end
|
314
422
|
|
423
|
+
|
424
|
+
it "should destroy properly" do
|
425
|
+
|
426
|
+
c1 = Category.create(scope)
|
427
|
+
c2 = Category.create(scope)
|
428
|
+
|
429
|
+
c3 = Category.create(scope2)
|
430
|
+
c4 = Category.create(scope2)
|
431
|
+
c5 = Category.create(scope2)
|
432
|
+
c6 = Category.create(scope2)
|
433
|
+
c5.move(:into => c4)
|
434
|
+
[c3,c4,c5,c6].each{|c| c.reload }
|
435
|
+
c4.move(:into => c3)
|
436
|
+
[c3,c4,c5,c6].each{|c| c.reload}
|
437
|
+
c6.move(:into => c3)
|
438
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
439
|
+
|
440
|
+
c1.pos.should eql([1,2])
|
441
|
+
c2.pos.should eql([3,4])
|
442
|
+
|
443
|
+
c3.pos.should eql([1,8])
|
444
|
+
c4.pos.should eql([2,5])
|
445
|
+
c5.pos.should eql([3,4])
|
446
|
+
c6.pos.should eql([6,7])
|
447
|
+
# These won't be received without the identity map
|
448
|
+
# c4.should_receive(:before_destroy_hook).once
|
449
|
+
# c5.should_receive(:before_destroy_hook).once
|
450
|
+
# c4.should_receive(:after_destroy_hook).once
|
451
|
+
# c5.should_receive(:after_destroy_hook).once
|
452
|
+
# c6.should_not_receive(:before_destroy_hook)
|
453
|
+
# c6.should_not_receive(:after_destroy_hook)
|
454
|
+
|
455
|
+
lambda {
|
456
|
+
c2.destroy
|
457
|
+
}.should_not raise_error
|
458
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
459
|
+
# c1.destroyed?.should be_false
|
460
|
+
Category.all(:id => c1.id).should_not be_empty
|
461
|
+
# c2.destroyed?.should be_true
|
462
|
+
Category.all(:id => c2.id).should be_empty
|
463
|
+
lambda {
|
464
|
+
c4.destroy
|
465
|
+
}.should_not raise_error
|
466
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
467
|
+
Category.all(:id => c4.id).should be_empty
|
468
|
+
Category.all(:id => c5.id).should be_empty
|
469
|
+
Category.all(:id => c3.id).should_not be_empty
|
470
|
+
Category.all(:id => c6.id).should_not be_empty
|
471
|
+
|
472
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
473
|
+
|
474
|
+
c3.pos.should eql([1, 4])
|
475
|
+
c6.pos.should eql([2, 3])
|
476
|
+
lambda {
|
477
|
+
c3.destroy!
|
478
|
+
}.should_not raise_error
|
479
|
+
Category.all.should have(1).items
|
480
|
+
Category.all.first.should eql(c1)
|
481
|
+
end
|
482
|
+
|
315
483
|
end
|
316
484
|
|
317
485
|
describe "with active DM Identity Map" do
|
@@ -320,6 +488,8 @@ describe DataMapper::Is::AwesomeSet do
|
|
320
488
|
Category.auto_migrate!
|
321
489
|
Discrim1.auto_migrate!
|
322
490
|
Discrim2.auto_migrate!
|
491
|
+
FileServer.auto_migrate!
|
492
|
+
FileServerItem.auto_migrate!
|
323
493
|
end
|
324
494
|
|
325
495
|
it "puts itself as the last root in the defined scope on initial save when using the identity map" do
|
@@ -373,6 +543,19 @@ describe DataMapper::Is::AwesomeSet do
|
|
373
543
|
end
|
374
544
|
end
|
375
545
|
|
546
|
+
|
547
|
+
it "moves itself into a parent with relationship scope update when using the identity map" do
|
548
|
+
repository do
|
549
|
+
s1 = FileServer.create({:name => 'foo'})
|
550
|
+
f1 = FileServerItem.create({:file_server => s1})
|
551
|
+
f2 = FileServerItem.new
|
552
|
+
f2.sco.should_not eql(f1.sco)
|
553
|
+
f2.move(:into => f1)
|
554
|
+
[f1, f2].each { |f| f.reload }
|
555
|
+
f2.sco.should eql(f1.sco)
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
376
559
|
it "moves around properly when using the identity map" do
|
377
560
|
repository do
|
378
561
|
c1 = Category.create(scope)
|
@@ -508,6 +691,23 @@ describe DataMapper::Is::AwesomeSet do
|
|
508
691
|
end
|
509
692
|
end
|
510
693
|
|
694
|
+
|
695
|
+
it "identifies the root with relationship scopes when using the identity map" do
|
696
|
+
# Root with relationship scope
|
697
|
+
repository do
|
698
|
+
s1 = FileServer.create({:name => 'foo'})
|
699
|
+
f1 = FileServerItem.create({:file_server => s1})
|
700
|
+
f2 = FileServerItem.create({:file_server => s1})
|
701
|
+
f3 = FileServerItem.create({:file_server => s1})
|
702
|
+
f2.move(:into => f1)
|
703
|
+
f3.move(:into => f2)
|
704
|
+
f2.root.should_not be_nil
|
705
|
+
f2.root.id.should eql(f1.id)
|
706
|
+
f3.root.should_not be_nil
|
707
|
+
f3.root.id.should eql(f1.id)
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
511
711
|
it "gets all roots in the current scope when using the identity map" do
|
512
712
|
repository do
|
513
713
|
c1 = Category.create(scope)
|
@@ -623,6 +823,64 @@ describe DataMapper::Is::AwesomeSet do
|
|
623
823
|
end
|
624
824
|
end
|
625
825
|
|
826
|
+
|
827
|
+
it "moves scope properly with relationships when using the identity map" do
|
828
|
+
repository do
|
829
|
+
# Relationship scope tests
|
830
|
+
s1 = FileServer.create({:name => 'foo'})
|
831
|
+
server1 = {:file_server => s1}
|
832
|
+
f1 = FileServerItem.create({:file_server => s1})
|
833
|
+
f2 = FileServerItem.create({:file_server => s1})
|
834
|
+
f3 = FileServerItem.create({:file_server => s1})
|
835
|
+
|
836
|
+
s2 = FileServer.create({:name => 'bar'})
|
837
|
+
server2 = {:file_server => s2}
|
838
|
+
f4 = FileServerItem.create({:file_server => s2})
|
839
|
+
f5 = FileServerItem.create({:file_server => s2})
|
840
|
+
f6 = FileServerItem.create({:file_server => s2})
|
841
|
+
|
842
|
+
f1.move(:into => f4)
|
843
|
+
[f1,f2,f3,f4,f5,f6].each { |c| c.reload }
|
844
|
+
f1.sco.should eql(server2)
|
845
|
+
|
846
|
+
f2.pos.should eql([1,2])
|
847
|
+
f3.pos.should eql([3,4])
|
848
|
+
|
849
|
+
f4.pos.should eql([1,4])
|
850
|
+
f1.pos.should eql([2,3])
|
851
|
+
f5.pos.should eql([5,6])
|
852
|
+
f6.pos.should eql([7,8])
|
853
|
+
|
854
|
+
f4.move(:into => f2)
|
855
|
+
[f1,f2,f3,f4,f5,f6].each { |c| c.reload }
|
856
|
+
f1.sco.should eql(server1)
|
857
|
+
f4.sco.should eql(server1)
|
858
|
+
|
859
|
+
f2.pos.should eql([1,6])
|
860
|
+
f4.pos.should eql([2,5])
|
861
|
+
f1.pos.should eql([3,4])
|
862
|
+
f3.pos.should eql([7,8])
|
863
|
+
|
864
|
+
|
865
|
+
f5.pos.should eql([1,2])
|
866
|
+
f6.pos.should eql([3,4])
|
867
|
+
|
868
|
+
# You can move into the root of a different scope by passing an object from that scope
|
869
|
+
# or a hash that represents that scope
|
870
|
+
f5.move(:root => server1)
|
871
|
+
[f1,f2,f3,f4,f5,f6].each { |c| c.reload }
|
872
|
+
f5.sco.should eql(server1)
|
873
|
+
|
874
|
+
f2.pos.should eql([1,6])
|
875
|
+
f4.pos.should eql([2,5])
|
876
|
+
f1.pos.should eql([3,4])
|
877
|
+
f3.pos.should eql([7,8])
|
878
|
+
f5.pos.should eql([9,10])
|
879
|
+
|
880
|
+
f6.pos.should eql([1,2])
|
881
|
+
end
|
882
|
+
end
|
883
|
+
|
626
884
|
it "should get all rows in the database if the discrimator is not part of scope when using the identity map" do
|
627
885
|
repository do
|
628
886
|
c1 = CatD11.create(scope)
|
@@ -644,6 +902,66 @@ describe DataMapper::Is::AwesomeSet do
|
|
644
902
|
end
|
645
903
|
end
|
646
904
|
|
905
|
+
|
906
|
+
it "should destroy properly when using identity map" do
|
907
|
+
repository do
|
908
|
+
c1 = Category.create(scope)
|
909
|
+
c2 = Category.create(scope)
|
910
|
+
|
911
|
+
c3 = Category.create(scope2)
|
912
|
+
c4 = Category.create(scope2)
|
913
|
+
c5 = Category.create(scope2)
|
914
|
+
c6 = Category.create(scope2)
|
915
|
+
c5.move(:into => c4)
|
916
|
+
[c3,c4,c5,c6].each{|c| c.reload }
|
917
|
+
c4.move(:into => c3)
|
918
|
+
[c3,c4,c5,c6].each{|c| c.reload}
|
919
|
+
c6.move(:into => c3)
|
920
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
921
|
+
|
922
|
+
c1.pos.should eql([1,2])
|
923
|
+
c2.pos.should eql([3,4])
|
924
|
+
|
925
|
+
c3.pos.should eql([1,8])
|
926
|
+
c4.pos.should eql([2,5])
|
927
|
+
c5.pos.should eql([3,4])
|
928
|
+
c6.pos.should eql([6,7])
|
929
|
+
c4.should_receive(:before_destroy_hook).once
|
930
|
+
c5.should_receive(:before_destroy_hook).once
|
931
|
+
c4.should_receive(:after_destroy_hook).once
|
932
|
+
c5.should_receive(:after_destroy_hook).once
|
933
|
+
c6.should_not_receive(:before_destroy_hook)
|
934
|
+
c6.should_not_receive(:after_destroy_hook)
|
935
|
+
|
936
|
+
lambda {
|
937
|
+
c2.destroy
|
938
|
+
}.should_not raise_error
|
939
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
940
|
+
# c1.destroyed?.should be_false
|
941
|
+
Category.all(:id => c1.id).should_not be_empty
|
942
|
+
# c2.destroyed?.should be_true
|
943
|
+
Category.all(:id => c2.id).should be_empty
|
944
|
+
lambda {
|
945
|
+
c4.destroy
|
946
|
+
}.should_not raise_error
|
947
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
948
|
+
Category.all(:id => c4.id).should be_empty
|
949
|
+
Category.all(:id => c5.id).should be_empty
|
950
|
+
Category.all(:id => c3.id).should_not be_empty
|
951
|
+
Category.all(:id => c6.id).should_not be_empty
|
952
|
+
|
953
|
+
[c1,c2,c3,c4,c5,c6].each { |c| c.reload }
|
954
|
+
|
955
|
+
c3.pos.should eql([1, 4])
|
956
|
+
c6.pos.should eql([2, 3])
|
957
|
+
lambda {
|
958
|
+
c3.destroy!
|
959
|
+
}.should_not raise_error
|
960
|
+
Category.all.should have(1).items
|
961
|
+
Category.all.first.should eql(c1)
|
962
|
+
end
|
963
|
+
end
|
964
|
+
|
647
965
|
end
|
648
966
|
|
649
967
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
require 'dm-core'
|
4
|
+
require 'dm-migrations'
|
4
5
|
require 'dm-adjust'
|
5
6
|
require 'dm-aggregates'
|
6
|
-
require 'dm-
|
7
|
-
require 'dm-validations'
|
7
|
+
require 'dm-transactions'
|
8
8
|
|
9
9
|
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
10
10
|
require 'dm-is-awesome_set'
|
@@ -93,6 +93,26 @@ end
|
|
93
93
|
class CatD22 < Discrim2
|
94
94
|
end
|
95
95
|
|
96
|
+
class FileServer
|
97
|
+
include DataMapper::Resource
|
98
|
+
|
99
|
+
property :id, Serial
|
100
|
+
property :name, String
|
101
|
+
end
|
102
|
+
|
103
|
+
class FileServerItem
|
104
|
+
include DataMapper::Resource
|
105
|
+
|
106
|
+
property :id, Serial
|
107
|
+
property :name, String
|
108
|
+
belongs_to :file_server
|
109
|
+
is :awesome_set, :scope => [:file_server]
|
110
|
+
# convenience methods only for speccing.
|
111
|
+
def pos; [lft,rgt] end
|
112
|
+
def sco; {:file_server => file_server}; end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
96
116
|
# Quick hack for ruby 1.8.6 - really, it's a hack. Don't use this anywhere else.
|
97
117
|
|
98
118
|
class Hash
|
data/tasks/spec.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-is-awesome_set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Jeremy Nicoll
|
@@ -11,49 +17,85 @@ autorequire:
|
|
11
17
|
bindir: bin
|
12
18
|
cert_chain: []
|
13
19
|
|
14
|
-
date: 2010-
|
20
|
+
date: 2010-07-09 00:00:00 -04:00
|
15
21
|
default_executable:
|
16
22
|
dependencies:
|
17
23
|
- !ruby/object:Gem::Dependency
|
18
24
|
name: dm-core
|
19
|
-
|
20
|
-
|
21
|
-
|
25
|
+
prerelease: false
|
26
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
22
28
|
requirements:
|
23
29
|
- - ~>
|
24
30
|
- !ruby/object:Gem::Version
|
25
|
-
|
26
|
-
|
31
|
+
hash: 15
|
32
|
+
segments:
|
33
|
+
- 1
|
34
|
+
- 0
|
35
|
+
version: "1.0"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
27
38
|
- !ruby/object:Gem::Dependency
|
28
39
|
name: dm-adjust
|
29
|
-
|
30
|
-
|
31
|
-
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
32
43
|
requirements:
|
33
44
|
- - ~>
|
34
45
|
- !ruby/object:Gem::Version
|
35
|
-
|
36
|
-
|
46
|
+
hash: 15
|
47
|
+
segments:
|
48
|
+
- 1
|
49
|
+
- 0
|
50
|
+
version: "1.0"
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
37
53
|
- !ruby/object:Gem::Dependency
|
38
54
|
name: dm-aggregates
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 15
|
62
|
+
segments:
|
63
|
+
- 1
|
64
|
+
- 0
|
65
|
+
version: "1.0"
|
39
66
|
type: :runtime
|
40
|
-
|
41
|
-
|
67
|
+
version_requirements: *id003
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: dm-transactions
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
42
73
|
requirements:
|
43
74
|
- - ~>
|
44
75
|
- !ruby/object:Gem::Version
|
45
|
-
|
46
|
-
|
76
|
+
hash: 15
|
77
|
+
segments:
|
78
|
+
- 1
|
79
|
+
- 0
|
80
|
+
version: "1.0"
|
81
|
+
type: :runtime
|
82
|
+
version_requirements: *id004
|
47
83
|
- !ruby/object:Gem::Dependency
|
48
84
|
name: rspec
|
49
|
-
|
50
|
-
|
51
|
-
|
85
|
+
prerelease: false
|
86
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
52
88
|
requirements:
|
53
89
|
- - ~>
|
54
90
|
- !ruby/object:Gem::Version
|
91
|
+
hash: 13
|
92
|
+
segments:
|
93
|
+
- 1
|
94
|
+
- 2
|
95
|
+
- 9
|
55
96
|
version: 1.2.9
|
56
|
-
|
97
|
+
type: :development
|
98
|
+
version_requirements: *id005
|
57
99
|
description: A library that lets any datamapper model act like a nested set
|
58
100
|
email: jnicoll@gnexp.com
|
59
101
|
executables: []
|
@@ -66,6 +108,7 @@ extra_rdoc_files:
|
|
66
108
|
- TODO
|
67
109
|
files:
|
68
110
|
- .gitignore
|
111
|
+
- Gemfile
|
69
112
|
- LICENSE
|
70
113
|
- README
|
71
114
|
- Rakefile
|
@@ -93,21 +136,27 @@ rdoc_options:
|
|
93
136
|
require_paths:
|
94
137
|
- lib
|
95
138
|
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
none: false
|
96
140
|
requirements:
|
97
141
|
- - ">="
|
98
142
|
- !ruby/object:Gem::Version
|
143
|
+
hash: 3
|
144
|
+
segments:
|
145
|
+
- 0
|
99
146
|
version: "0"
|
100
|
-
version:
|
101
147
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
none: false
|
102
149
|
requirements:
|
103
150
|
- - ">="
|
104
151
|
- !ruby/object:Gem::Version
|
152
|
+
hash: 3
|
153
|
+
segments:
|
154
|
+
- 0
|
105
155
|
version: "0"
|
106
|
-
version:
|
107
156
|
requirements: []
|
108
157
|
|
109
158
|
rubyforge_project:
|
110
|
-
rubygems_version: 1.3.
|
159
|
+
rubygems_version: 1.3.7
|
111
160
|
signing_key:
|
112
161
|
specification_version: 3
|
113
162
|
summary: A nested set plugin for datamapper
|