dm-is-nested_set 0.9.11 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{History.txt → History.rdoc} +4 -0
- data/Manifest.txt +2 -2
- data/{README.txt → README.rdoc} +0 -0
- data/Rakefile +2 -3
- data/lib/dm-is-nested_set/is/nested_set.rb +68 -64
- data/lib/dm-is-nested_set/is/version.rb +1 -1
- data/lib/dm-is-nested_set.rb +2 -8
- data/spec/integration/nested_set_spec.rb +44 -47
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +11 -8
- data/tasks/install.rb +1 -1
- data/tasks/spec.rb +4 -4
- metadata +14 -31
data/Manifest.txt
CHANGED
data/{README.txt → README.rdoc}
RENAMED
File without changes
|
data/Rakefile
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'pathname'
|
2
|
-
require 'rubygems'
|
3
2
|
|
4
3
|
ROOT = Pathname(__FILE__).dirname.expand_path
|
5
4
|
JRUBY = RUBY_PLATFORM =~ /java/
|
@@ -14,10 +13,10 @@ GEM_NAME = 'dm-is-nested_set'
|
|
14
13
|
GEM_VERSION = DataMapper::Is::NestedSet::VERSION
|
15
14
|
GEM_DEPENDENCIES = [['dm-core', GEM_VERSION], ['dm-adjust', GEM_VERSION]]
|
16
15
|
GEM_CLEAN = %w[ log pkg coverage ]
|
17
|
-
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.
|
16
|
+
GEM_EXTRAS = { :has_rdoc => true, :extra_rdoc_files => %w[ README.rdoc LICENSE TODO History.rdoc ] }
|
18
17
|
|
19
18
|
PROJECT_NAME = 'datamapper'
|
20
|
-
PROJECT_URL = "http://github.com/
|
19
|
+
PROJECT_URL = "http://github.com/datamapper/dm-more/tree/master/#{GEM_NAME}"
|
21
20
|
PROJECT_DESCRIPTION = PROJECT_SUMMARY = 'DataMapper plugin allowing the creation of nested sets from data models'
|
22
21
|
|
23
22
|
[ ROOT, ROOT.parent ].each do |dir|
|
@@ -6,12 +6,12 @@ module DataMapper
|
|
6
6
|
# docs in the works
|
7
7
|
#
|
8
8
|
def is_nested_set(options={})
|
9
|
-
options = { :child_key => [:parent_id], :scope => [] }.merge(options)
|
9
|
+
options = { :child_key => [ :parent_id ], :scope => [] }.merge(options)
|
10
10
|
|
11
11
|
extend DataMapper::Is::NestedSet::ClassMethods
|
12
12
|
include DataMapper::Is::NestedSet::InstanceMethods
|
13
13
|
|
14
|
-
@nested_set_scope
|
14
|
+
@nested_set_scope = options[:scope]
|
15
15
|
@nested_set_parent = options[:child_key]
|
16
16
|
|
17
17
|
property :lft, Integer, :writer => :private
|
@@ -21,36 +21,36 @@ module DataMapper
|
|
21
21
|
# be cut down to 1 instead of 2 queries. this would be the other way, but seems hackish:
|
22
22
|
# options[:child_key].each{|pname| property(pname, Integer) unless properties.detect{|p| p.name == pname}}
|
23
23
|
|
24
|
-
belongs_to :parent, :
|
25
|
-
has n, :children, :
|
24
|
+
belongs_to :parent, :model => self, :child_key => options[:child_key], :order => [ :lft ], :nullable => true
|
25
|
+
has n, :children, :model => self, :child_key => options[:child_key], :order => [ :lft ]
|
26
26
|
|
27
27
|
before :create do
|
28
|
-
if !
|
28
|
+
if !parent
|
29
29
|
# TODO must change for nested sets
|
30
|
-
|
31
|
-
elsif
|
32
|
-
|
30
|
+
root ? move_without_saving(:into => root) : move_without_saving(:to => 1)
|
31
|
+
elsif parent && !lft
|
32
|
+
move_without_saving(:into => parent)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
before :update do
|
37
|
-
if
|
37
|
+
if nested_set_scope != original_nested_set_scope
|
38
38
|
# TODO detach from old list first. many edge-cases here, need good testing
|
39
|
-
self.lft,self.rgt = nil,nil
|
40
|
-
#puts "#{
|
41
|
-
|
42
|
-
elsif (
|
39
|
+
self.lft, self.rgt = nil, nil
|
40
|
+
#puts "#{root.inspect} - #{[nested_set_scope,original_nested_set_scope].inspect}"
|
41
|
+
root ? move_without_saving(:into => root) : move_without_saving(:to => 1)
|
42
|
+
elsif (parent && !lft) || (parent != ancestor)
|
43
43
|
# if the parent is set, we try to move this into that parent, otherwise move into root.
|
44
|
-
|
44
|
+
parent ? move_without_saving(:into => parent) : move_without_saving(:into => model.root)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
before :destroy do
|
49
|
-
|
49
|
+
send(:detach)
|
50
50
|
end
|
51
51
|
|
52
|
-
after_class_method :inherited do |retval,target|
|
53
|
-
target.instance_variable_set(:@nested_set_scope,
|
52
|
+
after_class_method :inherited do |retval, target|
|
53
|
+
target.instance_variable_set(:@nested_set_scope, @nested_set_scope.dup)
|
54
54
|
target.instance_variable_set(:@nested_set_parent, @nested_set_parent.dup)
|
55
55
|
end
|
56
56
|
|
@@ -60,8 +60,8 @@ module DataMapper
|
|
60
60
|
attr_reader :nested_set_scope, :nested_set_parent
|
61
61
|
|
62
62
|
def adjust_gap!(scoped_set,at,adjustment)
|
63
|
-
scoped_set.all(:rgt.gt => at).adjust!({:rgt => adjustment},true)
|
64
|
-
scoped_set.all(:lft.gt => at).adjust!({:lft => adjustment},true)
|
63
|
+
scoped_set.all(:rgt.gt => at).adjust!({ :rgt => adjustment }, true)
|
64
|
+
scoped_set.all(:lft.gt => at).adjust!({ :lft => adjustment }, true)
|
65
65
|
end
|
66
66
|
|
67
67
|
##
|
@@ -88,7 +88,7 @@ module DataMapper
|
|
88
88
|
def leaves
|
89
89
|
# TODO scoping, how should it act?
|
90
90
|
# TODO supply filtering-option?
|
91
|
-
all(:conditions => [
|
91
|
+
all(:conditions => [ 'rgt = lft + ?', 1 ], :order => [ :lft ])
|
92
92
|
end
|
93
93
|
|
94
94
|
##
|
@@ -104,7 +104,7 @@ module DataMapper
|
|
104
104
|
##
|
105
105
|
# rebuilds the nested set using parent/child relationships and a chosen order
|
106
106
|
#
|
107
|
-
def rebuild_set_from_tree(order=nil)
|
107
|
+
def rebuild_set_from_tree(order = nil)
|
108
108
|
# TODO pending
|
109
109
|
end
|
110
110
|
end
|
@@ -115,7 +115,7 @@ module DataMapper
|
|
115
115
|
#
|
116
116
|
# @private
|
117
117
|
def nested_set_scope
|
118
|
-
|
118
|
+
model.base_model.nested_set_scope.map{ |p| [ p, attribute_get(p) ] }.to_hash
|
119
119
|
end
|
120
120
|
|
121
121
|
##
|
@@ -123,7 +123,7 @@ module DataMapper
|
|
123
123
|
# @private
|
124
124
|
def original_nested_set_scope
|
125
125
|
# TODO commit
|
126
|
-
|
126
|
+
model.base_model.nested_set_scope.map{ |p| [ p, (property = properties[p]) && original_attributes.key?(property) ? original_attributes[property] : attribute_get(p) ] }.to_hash
|
127
127
|
end
|
128
128
|
|
129
129
|
##
|
@@ -131,7 +131,7 @@ module DataMapper
|
|
131
131
|
#
|
132
132
|
def nested_set
|
133
133
|
# TODO add option for serving it as a nested array
|
134
|
-
|
134
|
+
model.base_model.all(nested_set_scope.merge(:order => [ :lft ]))
|
135
135
|
end
|
136
136
|
|
137
137
|
##
|
@@ -167,21 +167,25 @@ module DataMapper
|
|
167
167
|
##
|
168
168
|
# @see move
|
169
169
|
def move_without_saving(vector)
|
170
|
-
if vector.
|
170
|
+
if vector.kind_of?(Hash)
|
171
|
+
action, object = vector.keys[0], vector.values[0]
|
172
|
+
else
|
173
|
+
action = vector
|
174
|
+
end
|
171
175
|
|
172
176
|
changed_scope = nested_set_scope != original_nested_set_scope
|
173
177
|
|
174
178
|
position = case action
|
175
|
-
when :higher then left_sibling ? left_sibling.lft
|
176
|
-
when :highest then ancestor ? ancestor.lft+1 : nil
|
177
|
-
when :lower then right_sibling ? right_sibling.rgt+1 : nil
|
178
|
-
when :lowest then ancestor ? ancestor.rgt
|
179
|
-
when :indent then left_sibling ? left_sibling.rgt
|
180
|
-
when :outdent then ancestor ? ancestor.rgt+1 : nil
|
181
|
-
when :into then object ? object.rgt
|
182
|
-
when :above then object ? object.lft
|
183
|
-
when :below then object ? object.rgt+1 : nil
|
184
|
-
when :to then object ? object.to_i
|
179
|
+
when :higher then left_sibling ? left_sibling.lft : nil # : "already at the top"
|
180
|
+
when :highest then ancestor ? ancestor.lft + 1 : nil # : "is root, or has no parent"
|
181
|
+
when :lower then right_sibling ? right_sibling.rgt + 1 : nil # : "already at the bottom"
|
182
|
+
when :lowest then ancestor ? ancestor.rgt : nil # : "is root, or has no parent"
|
183
|
+
when :indent then left_sibling ? left_sibling.rgt : nil # : "cannot find a sibling to indent into"
|
184
|
+
when :outdent then ancestor ? ancestor.rgt + 1 : nil # : "is root, or has no parent"
|
185
|
+
when :into then object ? object.rgt : nil # : "supply an object"
|
186
|
+
when :above then object ? object.lft : nil # : "supply an object"
|
187
|
+
when :below then object ? object.rgt + 1 : nil # : "supply an object"
|
188
|
+
when :to then object ? object.to_i : nil # : "supply a number"
|
185
189
|
end
|
186
190
|
|
187
191
|
##
|
@@ -192,45 +196,45 @@ module DataMapper
|
|
192
196
|
# raise UnableToPositionError unless position.is_a?(Integer) && position > 0
|
193
197
|
return false if !position || position < 1
|
194
198
|
# return false if you are trying to move this into another scope
|
195
|
-
return false if [:into, :above
|
199
|
+
return false if [ :into, :above, :below ].include?(action) && nested_set_scope != object.nested_set_scope
|
196
200
|
# if node is already in the requested position
|
197
|
-
if
|
198
|
-
self.parent =
|
201
|
+
if lft == position || rgt == position - 1
|
202
|
+
self.parent = ancestor # must set this again, because it might have been changed by the user before move.
|
199
203
|
return false
|
200
204
|
end
|
201
205
|
|
202
|
-
|
203
|
-
DataMapper::Transaction.new(self.repository) do |transaction|
|
206
|
+
model.transaction do
|
204
207
|
|
205
208
|
##
|
206
209
|
# if this node is already positioned we need to move it, and close the gap it leaves behind etc
|
207
210
|
# otherwise we only need to open a gap in the set, and smash that buggar in
|
208
211
|
#
|
209
|
-
if
|
210
|
-
# raise exception if node is trying to move into one of its descendants (
|
211
|
-
raise RecursiveNestingError if position >
|
212
|
+
if lft && rgt
|
213
|
+
# raise exception if node is trying to move into one of its descendants (infinite loop, spacetime will warp)
|
214
|
+
raise RecursiveNestingError if position > lft && position < rgt
|
212
215
|
# find out how wide this node is, as we need to make a gap large enough for it to fit in
|
213
|
-
gap =
|
216
|
+
gap = rgt - lft + 1
|
214
217
|
|
215
218
|
# make a gap at position, that is as wide as this node
|
216
|
-
|
219
|
+
model.base_model.adjust_gap!(nested_set, position - 1, gap)
|
217
220
|
|
218
221
|
# offset this node (and all its descendants) to the right position
|
219
|
-
|
220
|
-
old_position =
|
222
|
+
reload_attributes([ :lft, :rgt ])
|
223
|
+
old_position = lft
|
221
224
|
offset = position - old_position
|
222
225
|
|
223
|
-
nested_set.all(:rgt =>
|
226
|
+
nested_set.all(:rgt => lft..rgt).adjust!({ :lft => offset, :rgt => offset }, true)
|
227
|
+
|
224
228
|
# close the gap this movement left behind.
|
225
|
-
|
226
|
-
|
229
|
+
model.base_model.adjust_gap!(nested_set, old_position, -gap)
|
230
|
+
reload_attributes([ :lft, :rgt ])
|
227
231
|
else
|
228
232
|
# make a gap where the new node can be inserted
|
229
|
-
|
233
|
+
model.base_model.adjust_gap!(nested_set, position - 1, 2)
|
230
234
|
# set the position fields
|
231
235
|
self.lft, self.rgt = position, position + 1
|
232
236
|
end
|
233
|
-
self.parent =
|
237
|
+
self.parent = ancestor
|
234
238
|
end
|
235
239
|
end
|
236
240
|
|
@@ -258,7 +262,7 @@ module DataMapper
|
|
258
262
|
# @see #self_and_ancestors
|
259
263
|
def ancestors
|
260
264
|
nested_set.all(:lft.lt => lft, :rgt.gt => rgt)
|
261
|
-
#self_and_ancestors.reject{|r| r.key ==
|
265
|
+
#self_and_ancestors.reject{|r| r.key == key } # because identitymap is not used in console
|
262
266
|
end
|
263
267
|
|
264
268
|
##
|
@@ -266,7 +270,7 @@ module DataMapper
|
|
266
270
|
#
|
267
271
|
# @return <Resource, NilClass> returns the parent-object, or nil if this is root/detached
|
268
272
|
def ancestor
|
269
|
-
ancestors.
|
273
|
+
ancestors.last
|
270
274
|
end
|
271
275
|
|
272
276
|
##
|
@@ -302,7 +306,7 @@ module DataMapper
|
|
302
306
|
def descendants
|
303
307
|
# TODO add argument for returning as a nested array.
|
304
308
|
# TODO supply filtering-option?
|
305
|
-
nested_set.all(:lft => (lft+1)..(rgt-1))
|
309
|
+
nested_set.all(:lft => (lft + 1)..(rgt - 1))
|
306
310
|
end
|
307
311
|
|
308
312
|
##
|
@@ -311,7 +315,7 @@ module DataMapper
|
|
311
315
|
# @return <Collection>
|
312
316
|
def leaves
|
313
317
|
# TODO supply filtering-option?
|
314
|
-
nested_set.all(:lft => (lft+1)..rgt, :conditions=>[
|
318
|
+
nested_set.all(:lft => (lft + 1)..rgt, :conditions => [ 'rgt = lft + ?', 1 ])
|
315
319
|
end
|
316
320
|
|
317
321
|
##
|
@@ -320,7 +324,7 @@ module DataMapper
|
|
320
324
|
#
|
321
325
|
# @par
|
322
326
|
def leaf?
|
323
|
-
rgt-lft == 1
|
327
|
+
rgt - lft == 1
|
324
328
|
end
|
325
329
|
|
326
330
|
##
|
@@ -328,7 +332,7 @@ module DataMapper
|
|
328
332
|
#
|
329
333
|
# @return <Collection>
|
330
334
|
def self_and_siblings
|
331
|
-
parent ? parent.children : [self]
|
335
|
+
parent ? parent.children : [ self ]
|
332
336
|
end
|
333
337
|
|
334
338
|
##
|
@@ -339,7 +343,7 @@ module DataMapper
|
|
339
343
|
def siblings
|
340
344
|
# TODO find a way to return this as a collection?
|
341
345
|
# TODO supply filtering-option?
|
342
|
-
self_and_siblings.reject{|r| r.key ==
|
346
|
+
self_and_siblings.reject { |r| r.key == key } # because identitymap is not used in console
|
343
347
|
end
|
344
348
|
|
345
349
|
##
|
@@ -348,7 +352,7 @@ module DataMapper
|
|
348
352
|
# @return <Resource, NilClass> the resource to the left, or nil if self is leftmost
|
349
353
|
# @see #self_and_siblings
|
350
354
|
def left_sibling
|
351
|
-
self_and_siblings.
|
355
|
+
self_and_siblings.detect { |v| v.rgt == lft - 1 }
|
352
356
|
end
|
353
357
|
|
354
358
|
##
|
@@ -357,14 +361,14 @@ module DataMapper
|
|
357
361
|
# @return <Resource, NilClass> the resource to the right, or nil if self is rightmost
|
358
362
|
# @see #self_and_siblings
|
359
363
|
def right_sibling
|
360
|
-
self_and_siblings.
|
364
|
+
self_and_siblings.detect { |v| v.lft == rgt + 1 }
|
361
365
|
end
|
362
366
|
|
363
367
|
private
|
364
368
|
def detach
|
365
|
-
offset =
|
366
|
-
|
367
|
-
self.lft,self.rgt = nil,nil
|
369
|
+
offset = lft - rgt - 1
|
370
|
+
model.base_model.adjust_gap!(nested_set, rgt, offset)
|
371
|
+
self.lft, self.rgt = nil, nil
|
368
372
|
end
|
369
373
|
|
370
374
|
end
|
data/lib/dm-is-nested_set.rb
CHANGED
@@ -1,10 +1,4 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'rubygems'
|
3
|
-
|
4
|
-
gem 'dm-core', '0.9.11'
|
5
|
-
require 'dm-core'
|
6
|
-
|
7
|
-
#gem 'dm-adjust', '0.9.11'
|
8
1
|
require 'dm-adjust'
|
9
2
|
|
10
|
-
require
|
3
|
+
require 'dm-is-nested_set/is/nested_set'
|
4
|
+
require 'dm-is-nested_set/is/version'
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
1
|
+
require 'spec_helper'
|
3
2
|
|
4
3
|
if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
5
4
|
|
@@ -33,7 +32,7 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
33
32
|
class ::User
|
34
33
|
include DataMapper::Resource
|
35
34
|
|
36
|
-
property :id,
|
35
|
+
property :id, Serial
|
37
36
|
property :name, String
|
38
37
|
|
39
38
|
has n, :categories
|
@@ -43,8 +42,8 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
43
42
|
class ::Category
|
44
43
|
include DataMapper::Resource
|
45
44
|
|
46
|
-
property :id,
|
47
|
-
property :name,
|
45
|
+
property :id, Serial
|
46
|
+
property :name, String
|
48
47
|
property :class_name, Discriminator
|
49
48
|
|
50
49
|
belongs_to :user
|
@@ -59,26 +58,26 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
59
58
|
|
60
59
|
DataMapper.auto_migrate!
|
61
60
|
|
62
|
-
repository
|
63
|
-
@
|
64
|
-
@
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
61
|
+
DataMapper.repository do
|
62
|
+
@user = User.create(:name => 'paul')
|
63
|
+
@other = User.create(:name => 'john')
|
64
|
+
|
65
|
+
electronics = @user.categories.create( :name => 'Electronics')
|
66
|
+
televisions = @user.categories.create(:parent => electronics, :name => 'Televisions')
|
67
|
+
tube = @user.categories.create(:parent => televisions, :name => 'Tube')
|
68
|
+
lcd = @user.categories.create(:parent => televisions, :name => 'LCD')
|
69
|
+
plasma = @user.categories.create(:parent => televisions, :name => 'Plasma')
|
70
|
+
portable_electronics = @user.categories.create(:parent => electronics, :name => 'Portable Electronics')
|
71
|
+
mp3_players = @user.categories.create(:parent => portable_electronics, :name => 'MP3 Players')
|
72
|
+
flash = @user.categories.create(:parent => mp3_players, :name => 'Flash')
|
73
|
+
cd_players = @user.categories.create(:parent => portable_electronics, :name => 'CD Players')
|
74
|
+
two_way_radios = @user.categories.create(:parent => portable_electronics, :name => '2 Way Radios')
|
76
75
|
end
|
77
76
|
end
|
78
77
|
|
79
78
|
describe 'Class#rebuild_tree_from_set' do
|
80
79
|
it 'should reset all parent_ids correctly' do
|
81
|
-
repository(:default) do
|
80
|
+
DataMapper.repository(:default) do
|
82
81
|
plasma = Category.get(5)
|
83
82
|
plasma.parent_id.should == 2
|
84
83
|
plasma.ancestor.id.should == 2
|
@@ -92,13 +91,13 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
92
91
|
|
93
92
|
describe 'Class#root and #root' do
|
94
93
|
it 'should return the toplevel node' do
|
95
|
-
Category.root.name.should ==
|
94
|
+
Category.root.name.should == 'Electronics'
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
99
98
|
describe 'Class#leaves and #leaves' do
|
100
99
|
it 'should return all nodes without descendants' do
|
101
|
-
repository(:default) do
|
100
|
+
DataMapper.repository(:default) do
|
102
101
|
Category.leaves.length.should == 6
|
103
102
|
|
104
103
|
r = Category.root
|
@@ -110,56 +109,56 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
110
109
|
|
111
110
|
describe '#ancestor, #ancestors and #self_and_ancestors' do
|
112
111
|
it 'should return ancestors in an array' do
|
113
|
-
repository(:default) do |repos|
|
112
|
+
DataMapper.repository(:default) do |repos|
|
114
113
|
c8 = Category.get(8)
|
115
114
|
c8.ancestor.should == Category.get(7)
|
116
115
|
c8.ancestor.should == c8.parent
|
117
116
|
|
118
|
-
c8.ancestors.map{|a|a.name}.should == [
|
119
|
-
c8.self_and_ancestors.map{|a|a.name}.should == [
|
117
|
+
c8.ancestors.map{|a|a.name}.should == ['Electronics','Portable Electronics','MP3 Players']
|
118
|
+
c8.self_and_ancestors.map{|a|a.name}.should == ['Electronics','Portable Electronics','MP3 Players','Flash']
|
120
119
|
end
|
121
120
|
end
|
122
121
|
end
|
123
122
|
|
124
123
|
describe '#children' do
|
125
124
|
it 'should return children of node' do
|
126
|
-
repository(:default) do |repos|
|
125
|
+
DataMapper.repository(:default) do |repos|
|
127
126
|
r = Category.root
|
128
127
|
r.children.length.should == 2
|
129
128
|
|
130
129
|
t = r.children.first
|
131
130
|
t.children.length.should == 3
|
132
|
-
t.children.first.name.should ==
|
133
|
-
t.children[2].name.should ==
|
131
|
+
t.children.first.name.should == 'Tube'
|
132
|
+
t.children[2].name.should == 'Plasma'
|
134
133
|
end
|
135
134
|
end
|
136
135
|
end
|
137
136
|
|
138
137
|
describe '#descendants and #self_and_descendants' do
|
139
138
|
it 'should return all subnodes of node' do
|
140
|
-
repository(:default) do
|
139
|
+
DataMapper.repository(:default) do
|
141
140
|
r = Category.get(1)
|
142
141
|
r.self_and_descendants.length.should == 10
|
143
142
|
r.descendants.length.should == 9
|
144
|
-
r.name.should ==
|
143
|
+
r.name.should == 'Electronics'
|
145
144
|
t = r.children[1]
|
146
|
-
t.name.should ==
|
145
|
+
t.name.should == 'Portable Electronics'
|
147
146
|
t.descendants.length.should == 4
|
148
|
-
t.descendants.map{|a|a.name}.should == [
|
147
|
+
t.descendants.map{|a|a.name}.should == ['MP3 Players','Flash','CD Players','2 Way Radios']
|
149
148
|
end
|
150
149
|
end
|
151
150
|
end
|
152
151
|
|
153
152
|
describe '#siblings and #self_and_siblings' do
|
154
153
|
it 'should return all siblings of node' do
|
155
|
-
repository(:default) do
|
154
|
+
DataMapper.repository(:default) do
|
156
155
|
r = Category.root
|
157
156
|
r.self_and_siblings.length.should == 1
|
158
157
|
r.descendants.length.should == 9
|
159
158
|
|
160
159
|
televisions = r.children[0]
|
161
160
|
televisions.siblings.length.should == 1
|
162
|
-
televisions.siblings.map{|a|a.name}.should == [
|
161
|
+
televisions.siblings.map{|a|a.name}.should == ['Portable Electronics']
|
163
162
|
end
|
164
163
|
end
|
165
164
|
end
|
@@ -181,7 +180,7 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
181
180
|
# 10 | 17 | 18 | - 2 Way Radios
|
182
181
|
|
183
182
|
it 'should move items correctly with :higher / :highest / :lower / :lowest' do
|
184
|
-
repository(:default) do |repos|
|
183
|
+
DataMapper.repository(:default) do |repos|
|
185
184
|
|
186
185
|
Category.get(4).pos.should == [5,6]
|
187
186
|
|
@@ -212,7 +211,7 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
212
211
|
end
|
213
212
|
|
214
213
|
it 'should move items correctly with :indent / :outdent' do
|
215
|
-
repository(:default) do |repos|
|
214
|
+
DataMapper.repository(:default) do |repos|
|
216
215
|
|
217
216
|
mp3_players = Category.get(7)
|
218
217
|
|
@@ -240,18 +239,18 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
240
239
|
|
241
240
|
describe 'moving objects with #move_* #and place_node_at' do
|
242
241
|
it 'should set left/right when choosing a parent' do
|
243
|
-
repository(:default) do |repos|
|
242
|
+
DataMapper.repository(:default) do |repos|
|
244
243
|
Category.auto_migrate!
|
245
244
|
|
246
|
-
c1 =
|
245
|
+
c1 = @user.categories.create(:name => 'New Electronics')
|
247
246
|
|
248
|
-
c2 =
|
247
|
+
c2 = @user.categories.create(:name => 'OLED TVs')
|
249
248
|
|
250
249
|
c1.pos.should == [1,4]
|
251
250
|
c1.root.should == c1
|
252
251
|
c2.pos.should == [2,3]
|
253
252
|
|
254
|
-
c3 =
|
253
|
+
c3 = @user.categories.create(:name => 'Portable Electronics')
|
255
254
|
c3.parent=c1
|
256
255
|
c3.save
|
257
256
|
|
@@ -273,8 +272,8 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
273
272
|
c2.pos.should == [2,5]
|
274
273
|
c3.pos.should == [3,4]
|
275
274
|
|
276
|
-
c4 =
|
277
|
-
c5 =
|
275
|
+
c4 = @user.categories.create(:name => 'Tube', :parent => c2)
|
276
|
+
c5 = @user.categories.create(:name => 'Flatpanel', :parent => c2)
|
278
277
|
|
279
278
|
c1.pos.should == [1,10]
|
280
279
|
c2.pos.should == [2,9]
|
@@ -293,11 +292,10 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
293
292
|
|
294
293
|
describe 'scoping' do
|
295
294
|
it 'should detach from list when changing scope' do
|
296
|
-
repository(:default) do |repos|
|
295
|
+
DataMapper.repository(:default) do |repos|
|
297
296
|
plasma = Category.get(5)
|
298
297
|
plasma.pos.should == [7,8]
|
299
|
-
plasma.
|
300
|
-
plasma.save
|
298
|
+
plasma.update(:user => @other)
|
301
299
|
plasma.pos.should == [1,2]
|
302
300
|
end
|
303
301
|
end
|
@@ -305,7 +303,7 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
305
303
|
|
306
304
|
describe 'integrity' do
|
307
305
|
it 'should detach object from list when deleted' do
|
308
|
-
repository(:default) do |repos|
|
306
|
+
DataMapper.repository(:default) do |repos|
|
309
307
|
lcd = Category.get(4)
|
310
308
|
lcd.pos.should == [5,6]
|
311
309
|
Category.get(3).destroy
|
@@ -313,6 +311,5 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
313
311
|
end
|
314
312
|
end
|
315
313
|
end
|
316
|
-
|
317
314
|
end
|
318
315
|
end
|
data/spec/spec.opts
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,19 @@
|
|
1
|
-
require 'pathname'
|
2
1
|
require 'rubygems'
|
3
2
|
|
4
|
-
|
5
|
-
|
3
|
+
# use local dm-core if running from a typical dev checkout.
|
4
|
+
lib = File.join('..', '..', 'dm-core', 'lib')
|
5
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib)
|
6
|
+
require 'dm-core'
|
6
7
|
|
7
|
-
|
8
|
+
# use local dm-adjust if running from a typical dev checkout.
|
9
|
+
lib = File.join('..', 'dm-adjust', 'lib')
|
10
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib)
|
11
|
+
require 'dm-adjust'
|
8
12
|
|
9
|
-
#
|
10
|
-
lib
|
11
|
-
$LOAD_PATH.unshift(lib) if lib.directory?
|
13
|
+
# Support running specs with 'rake spec' and 'spec'
|
14
|
+
$LOAD_PATH.unshift('lib') unless $LOAD_PATH.include?('lib')
|
12
15
|
|
13
|
-
require
|
16
|
+
require 'dm-is-nested_set'
|
14
17
|
|
15
18
|
def load_driver(name, default_uri)
|
16
19
|
return false if ENV['ADAPTER'] != name.to_s
|
data/tasks/install.rb
CHANGED
@@ -4,7 +4,7 @@ end
|
|
4
4
|
|
5
5
|
desc "Install #{GEM_NAME} #{GEM_VERSION}"
|
6
6
|
task :install => [ :package ] do
|
7
|
-
sudo_gem "install
|
7
|
+
sudo_gem "install pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
|
8
8
|
end
|
9
9
|
|
10
10
|
desc "Uninstall #{GEM_NAME} #{GEM_VERSION}"
|
data/tasks/spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
1
|
begin
|
2
|
-
gem 'rspec', '~>1.2'
|
3
|
-
require 'spec'
|
4
2
|
require 'spec/rake/spectask'
|
5
3
|
|
6
4
|
task :default => [ :spec ]
|
@@ -8,16 +6,18 @@ begin
|
|
8
6
|
desc 'Run specifications'
|
9
7
|
Spec::Rake::SpecTask.new(:spec) do |t|
|
10
8
|
t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
|
11
|
-
t.
|
9
|
+
t.libs << 'lib' << 'spec' # needed for CI rake spec task, duplicated in spec_helper
|
12
10
|
|
13
11
|
begin
|
14
|
-
|
12
|
+
require 'rcov'
|
15
13
|
t.rcov = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
|
16
14
|
t.rcov_opts << '--exclude' << 'spec'
|
17
15
|
t.rcov_opts << '--text-summary'
|
18
16
|
t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
|
19
17
|
rescue LoadError
|
20
18
|
# rcov not installed
|
19
|
+
rescue SyntaxError
|
20
|
+
# rcov syntax invalid
|
21
21
|
end
|
22
22
|
end
|
23
23
|
rescue LoadError
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-is-nested_set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sindre Aarsaether
|
@@ -9,29 +9,10 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-16 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
name: dm-core
|
17
|
-
type: :runtime
|
18
|
-
version_requirement:
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
requirements:
|
21
|
-
- - "="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.9.11
|
24
|
-
version:
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: dm-adjust
|
27
|
-
type: :runtime
|
28
|
-
version_requirement:
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.9.11
|
34
|
-
version:
|
14
|
+
dependencies: []
|
15
|
+
|
35
16
|
description: DataMapper plugin allowing the creation of nested sets from data models
|
36
17
|
email:
|
37
18
|
- sindre [a] identu [d] no
|
@@ -40,15 +21,15 @@ executables: []
|
|
40
21
|
extensions: []
|
41
22
|
|
42
23
|
extra_rdoc_files:
|
43
|
-
- README.
|
24
|
+
- README.rdoc
|
44
25
|
- LICENSE
|
45
26
|
- TODO
|
46
|
-
- History.
|
27
|
+
- History.rdoc
|
47
28
|
files:
|
48
|
-
- History.
|
29
|
+
- History.rdoc
|
49
30
|
- LICENSE
|
50
31
|
- Manifest.txt
|
51
|
-
- README.
|
32
|
+
- README.rdoc
|
52
33
|
- Rakefile
|
53
34
|
- TODO
|
54
35
|
- lib/dm-is-nested_set.rb
|
@@ -60,11 +41,13 @@ files:
|
|
60
41
|
- tasks/install.rb
|
61
42
|
- tasks/spec.rb
|
62
43
|
has_rdoc: true
|
63
|
-
homepage: http://github.com/
|
44
|
+
homepage: http://github.com/datamapper/dm-more/tree/master/dm-is-nested_set
|
45
|
+
licenses: []
|
46
|
+
|
64
47
|
post_install_message:
|
65
48
|
rdoc_options:
|
66
49
|
- --main
|
67
|
-
- README.
|
50
|
+
- README.rdoc
|
68
51
|
require_paths:
|
69
52
|
- lib
|
70
53
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -82,9 +65,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
65
|
requirements: []
|
83
66
|
|
84
67
|
rubyforge_project: datamapper
|
85
|
-
rubygems_version: 1.3.
|
68
|
+
rubygems_version: 1.3.5
|
86
69
|
signing_key:
|
87
|
-
specification_version:
|
70
|
+
specification_version: 3
|
88
71
|
summary: DataMapper plugin allowing the creation of nested sets from data models
|
89
72
|
test_files: []
|
90
73
|
|