dm-is-list 0.9.11 → 0.10.0
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/History.rdoc +46 -0
- data/Manifest.txt +2 -2
- data/README.rdoc +220 -0
- data/Rakefile +2 -3
- data/lib/dm-is-list/is/list.rb +493 -78
- data/lib/dm-is-list/is/version.rb +1 -1
- data/lib/dm-is-list.rb +1 -9
- data/spec/integration/list_spec.rb +981 -140
- 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/History.txt +0 -17
- data/README.txt +0 -57
@@ -1,10 +1,9 @@
|
|
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
|
describe 'DataMapper::Is::List' do
|
6
5
|
|
7
|
-
class
|
6
|
+
class User
|
8
7
|
include DataMapper::Resource
|
9
8
|
|
10
9
|
property :id, Serial
|
@@ -13,10 +12,10 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
13
12
|
has n, :todos
|
14
13
|
end
|
15
14
|
|
16
|
-
class
|
15
|
+
class Todo
|
17
16
|
include DataMapper::Resource
|
18
17
|
|
19
|
-
property :id,
|
18
|
+
property :id, Serial
|
20
19
|
property :title, String
|
21
20
|
|
22
21
|
belongs_to :user
|
@@ -25,187 +24,1029 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
|
|
25
24
|
end
|
26
25
|
|
27
26
|
before :each do
|
28
|
-
User.auto_migrate!
|
29
|
-
Todo.auto_migrate!
|
30
|
-
|
31
|
-
u1 = User.create(:name => "Johnny")
|
32
|
-
Todo.create(:user => u1, :title => "Write down what is needed in a list-plugin")
|
33
|
-
Todo.create(:user => u1, :title => "Complete a temporary version of is-list")
|
34
|
-
Todo.create(:user => u1, :title => "Squash bugs in nested-set")
|
27
|
+
User.auto_migrate!
|
28
|
+
Todo.auto_migrate!
|
35
29
|
|
36
|
-
|
37
|
-
Todo.create(:user =>
|
38
|
-
Todo.create(:user =>
|
39
|
-
Todo.create(:user =>
|
30
|
+
@u1 = User.create(:name => 'Johnny')
|
31
|
+
Todo.create(:user => @u1, :title => 'Write down what is needed in a list-plugin')
|
32
|
+
Todo.create(:user => @u1, :title => 'Complete a temporary version of is-list')
|
33
|
+
Todo.create(:user => @u1, :title => 'Squash any reported bugs')
|
34
|
+
Todo.create(:user => @u1, :title => 'Make public and await public scrutiny')
|
35
|
+
Todo.create(:user => @u1, :title => 'Rinse and repeat')
|
36
|
+
@u2 = User.create(:name => 'Freddy')
|
37
|
+
Todo.create(:user => @u2, :title => 'Eat tasty cupcake')
|
38
|
+
Todo.create(:user => @u2, :title => 'Procrastinate on paid work')
|
39
|
+
Todo.create(:user => @u2, :title => 'Go to sleep')
|
40
|
+
end
|
40
41
|
|
42
|
+
##
|
43
|
+
# Keep things DRY shortcut
|
44
|
+
#
|
45
|
+
# todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
46
|
+
#
|
47
|
+
# todo_list(:user => @u2, :order => [:id]).should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
48
|
+
#
|
49
|
+
def todo_list(options={})
|
50
|
+
options = { :user => @u1, :order => [:position] }.merge(options)
|
51
|
+
Todo.all(:user => options[:user], :order => options[:order]).map{ |a| [a.id, a.position] }
|
41
52
|
end
|
42
53
|
|
43
|
-
describe
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
54
|
+
describe "Class Methods" do
|
55
|
+
|
56
|
+
describe "#repair_list" do
|
57
|
+
|
58
|
+
it "should repair a scoped list" do
|
59
|
+
DataMapper.repository(:default) do |repos|
|
60
|
+
items = Todo.all(:user => @u1, :order => [:position])
|
61
|
+
items.each{ |item| item.update(:position => [4,2,8,32,16][item.id - 1]) }
|
62
|
+
todo_list.should == [ [2, 2], [1, 4], [3, 8], [5, 16], [4, 32] ]
|
63
|
+
|
64
|
+
Todo.repair_list(:user_id => @u1.id)
|
65
|
+
todo_list.should == [ [2, 1], [1, 2], [3, 3], [5, 4], [4, 5] ]
|
66
|
+
end
|
51
67
|
end
|
52
|
-
end
|
53
68
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
69
|
+
it "should repair unscoped lists" do
|
70
|
+
DataMapper.repository(:default) do |repos|
|
71
|
+
Todo.all.map { |t| [t.id, t.position] }.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 1], [7, 2], [8, 3] ]
|
72
|
+
Todo.repair_list
|
73
|
+
# note the order, repairs lists based on position
|
74
|
+
Todo.all.map { |t| [t.id, t.position] }.should == [ [1, 1], [2, 3], [3, 5], [4, 7], [5, 8], [6, 2], [7, 4], [8, 6] ]
|
75
|
+
Todo.all(:order => [:position]).map { |t| t.id }.should == [1, 6, 2, 7, 3, 8, 4, 5]
|
76
|
+
end
|
58
77
|
end
|
59
|
-
end
|
60
78
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
79
|
+
end #/ #repair_list
|
80
|
+
|
81
|
+
end #/ Class Methods
|
82
|
+
|
83
|
+
describe "Instance Methods" do
|
84
|
+
|
85
|
+
describe "#move" do
|
86
|
+
|
87
|
+
describe ":higher" do
|
88
|
+
|
89
|
+
it "should move item :higher in list" do
|
90
|
+
DataMapper.repository(:default) do |repos|
|
91
|
+
Todo.get(2).move(:higher).should == true
|
92
|
+
todo_list.should == [ [2, 1], [1, 2], [3, 3], [4, 4], [5, 5] ]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should NOT move item :higher when first in list" do
|
97
|
+
DataMapper.repository(:default) do |repos|
|
98
|
+
Todo.get(1).move(:higher).should == false
|
99
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end #/ :higher
|
104
|
+
|
105
|
+
describe ":lower" do
|
106
|
+
|
107
|
+
it "should move item :lower in list" do
|
108
|
+
DataMapper.repository(:default) do |repos|
|
109
|
+
Todo.get(2).move(:lower).should == true
|
110
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should NOT move item :lower when last in list" do
|
115
|
+
DataMapper.repository(:default) do |repos|
|
116
|
+
Todo.get(5).move(:lower).should == false
|
117
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end #/ :lower
|
122
|
+
|
123
|
+
describe ":up" do
|
124
|
+
|
125
|
+
it "should move item :up in list" do
|
126
|
+
DataMapper.repository(:default) do |repos|
|
127
|
+
Todo.get(2).move(:up).should == true
|
128
|
+
todo_list.should == [ [2, 1], [1, 2], [3, 3], [4, 4], [5, 5] ]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should NOT move item :up when first in list" do
|
133
|
+
DataMapper.repository(:default) do |repos|
|
134
|
+
Todo.get(1).move(:up).should == false
|
135
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end #/ :up
|
140
|
+
|
141
|
+
describe ":down" do
|
142
|
+
|
143
|
+
it "should move item :down in list" do
|
144
|
+
DataMapper.repository(:default) do |repos|
|
145
|
+
Todo.get(2).move(:down).should == true
|
146
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should NOT move :down when last in list" do
|
151
|
+
DataMapper.repository(:default) do |repos|
|
152
|
+
Todo.get(5).move(:down).should == false
|
153
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end #/ :down
|
158
|
+
|
159
|
+
describe ":top" do
|
160
|
+
|
161
|
+
it "should move item to :top of list" do
|
162
|
+
DataMapper.repository(:default) do |repos|
|
163
|
+
Todo.get(5).move(:top).should == true
|
164
|
+
todo_list.should == [ [5, 1], [1, 2], [2, 3], [3, 4], [4, 5] ]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should NOT move item to :top of list when it is already first" do
|
169
|
+
DataMapper.repository(:default) do |repos|
|
170
|
+
Todo.get(1).move(:top).should == false
|
171
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end #/ :top
|
176
|
+
|
177
|
+
describe ":bottom" do
|
178
|
+
|
179
|
+
it "should move item to :bottom of list" do
|
180
|
+
DataMapper.repository(:default) do |repos|
|
181
|
+
Todo.get(2).move(:bottom).should == true
|
182
|
+
todo_list.should == [ [1, 1], [3, 2], [4, 3], [5, 4], [2, 5] ]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should NOT move item to :bottom of list when it is already last" do
|
187
|
+
DataMapper.repository(:default) do |repos|
|
188
|
+
Todo.get(5).move(:bottom).should == false
|
189
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end #/ :bottom
|
194
|
+
|
195
|
+
describe ":highest" do
|
196
|
+
|
197
|
+
it "should move item :highest in list" do
|
198
|
+
DataMapper.repository(:default) do |repos|
|
199
|
+
Todo.get(5).move(:highest).should == true
|
200
|
+
todo_list.should == [ [5, 1], [1, 2], [2, 3], [3, 4], [4, 5] ]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should NOT move item :highest in list when it is already first" do
|
205
|
+
DataMapper.repository(:default) do |repos|
|
206
|
+
Todo.get(1).move(:highest).should == false
|
207
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
end #/ :highest
|
212
|
+
|
213
|
+
describe ":lowest" do
|
214
|
+
|
215
|
+
it "should move item :lowest in list" do
|
216
|
+
DataMapper.repository(:default) do |repos|
|
217
|
+
Todo.get(2).move(:lowest).should == true
|
218
|
+
todo_list.should == [ [1, 1], [3, 2], [4, 3], [5, 4], [2, 5] ]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should NOT move item :lowest in list when it is already last" do
|
223
|
+
DataMapper.repository(:default) do |repos|
|
224
|
+
Todo.get(5).move(:lowest).should == false
|
225
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
end #/ :lowest
|
230
|
+
|
231
|
+
describe ":above" do
|
232
|
+
|
233
|
+
it "should move item :above another in list" do
|
234
|
+
DataMapper.repository(:default) do |repos|
|
235
|
+
Todo.get(3).move(:above => Todo.get(2) ).should == true
|
236
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should NOT move item :above itself" do
|
241
|
+
DataMapper.repository(:default) do |repos|
|
242
|
+
Todo.get(1).move(:above => Todo.get(1) ).should == false
|
243
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should NOT move item :above a lower item (it's already above)" do
|
248
|
+
DataMapper.repository(:default) do |repos|
|
249
|
+
Todo.get(1).move(:above => Todo.get(2) ).should == false
|
250
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should NOT move the item :above another item in a different scope" do
|
255
|
+
DataMapper.repository(:default) do |repos|
|
256
|
+
Todo.get(1).move(:above => Todo.get(6) ).should == false
|
257
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
end #/ :above
|
262
|
+
|
263
|
+
describe ":below" do
|
264
|
+
|
265
|
+
it "should move item :below another in list" do
|
266
|
+
DataMapper.repository(:default) do |repos|
|
267
|
+
Todo.get(2).move(:below => Todo.get(3) ).should == true
|
268
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should NOT move item :below itself" do
|
273
|
+
DataMapper.repository(:default) do |repos|
|
274
|
+
Todo.get(1).move(:below => Todo.get(1) ).should == false # is this logical ???
|
275
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should NOT move item :below a higher item (it's already below)" do
|
280
|
+
DataMapper.repository(:default) do |repos|
|
281
|
+
Todo.get(5).move(:below => Todo.get(4) ).should == false # is this logical ???
|
282
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should NOT move the item :below another item in a different scope" do
|
287
|
+
DataMapper.repository(:default) do |repos|
|
288
|
+
Todo.get(1).move(:below => Todo.get(6) ).should == false
|
289
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
end #/ :below
|
294
|
+
|
295
|
+
describe ":to" do
|
296
|
+
|
297
|
+
describe "=> FixNum" do
|
298
|
+
|
299
|
+
it "should move item to the position" do
|
300
|
+
DataMapper.repository(:default) do |repos|
|
301
|
+
Todo.get(2).move(:to => 3 ).should == true
|
302
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
it "should NOT move item to a position above the first item in list (negative position)" do
|
307
|
+
DataMapper.repository(:default) do |repos|
|
308
|
+
Todo.get(2).move(:to => -33 ).should == true
|
309
|
+
todo_list.should == [ [2, 1], [1, 2], [3, 3], [4, 4], [5, 5] ]
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should NOT move item to a position below the last item in list (out of range - position)" do
|
314
|
+
DataMapper.repository(:default) do |repos|
|
315
|
+
Todo.get(2).move(:to => 33 ).should == true
|
316
|
+
todo_list.should == [ [1, 1], [3, 2], [4, 3], [5, 4], [2, 5] ]
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
end #/ => FixNum
|
321
|
+
|
322
|
+
describe "=> String" do
|
323
|
+
|
324
|
+
it "should move item to the position" do
|
325
|
+
DataMapper.repository(:default) do |repos|
|
326
|
+
Todo.get(2).move(:to => '3' ).should == true
|
327
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should NOT move item to a position above the first item in list (negative position)" do
|
332
|
+
DataMapper.repository(:default) do |repos|
|
333
|
+
Todo.get(2).move(:to => '-33' ).should == true
|
334
|
+
todo_list.should == [ [2, 1], [1, 2], [3, 3], [4, 4], [5, 5] ]
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should NOT move item to a position below the last item in list (out of range - position)" do
|
339
|
+
DataMapper.repository(:default) do |repos|
|
340
|
+
Todo.get(2).move(:to => '33' ).should == true
|
341
|
+
todo_list.should == [ [1, 1], [3, 2], [4, 3], [5, 4], [2, 5] ]
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
end #/ => String
|
346
|
+
|
347
|
+
end #/ :to
|
348
|
+
|
349
|
+
describe "X (position as Integer)" do
|
350
|
+
|
351
|
+
it "should move item to the position" do
|
352
|
+
DataMapper.repository(:default) do |repos|
|
353
|
+
Todo.get(2).move(3).should == true
|
354
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
it "should move the same item to different positions multiple times" do
|
359
|
+
DataMapper.repository(:default) do |repos|
|
360
|
+
item = Todo.get(2)
|
361
|
+
|
362
|
+
item.move(3).should == true
|
363
|
+
todo_list.should == [ [1, 1], [3, 2], [2, 3], [4, 4], [5, 5] ]
|
364
|
+
|
365
|
+
item.move(1).should == true
|
366
|
+
todo_list.should == [ [2, 1], [1, 2], [3, 3], [4, 4], [5, 5] ]
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
it 'should NOT move item to a position above the first item in list (negative position)' do
|
371
|
+
DataMapper.repository(:default) do |repos|
|
372
|
+
Todo.get(2).move(-33).should == true
|
373
|
+
todo_list.should == [ [2, 1], [1, 2], [3, 3], [4, 4], [5, 5] ]
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
it 'should NOT move item to a position below the last item in list (out of range - position)' do
|
378
|
+
DataMapper.repository(:default) do |repos|
|
379
|
+
Todo.get(2).move(33).should == true
|
380
|
+
todo_list.should == [ [1, 1], [3, 2], [4, 3], [5, 4], [2, 5] ]
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
end #/ #move(X)
|
385
|
+
|
386
|
+
describe "#move(:non_existant_vector_symbol)" do
|
387
|
+
|
388
|
+
it "should raise an ArgumentError when given an un-recognised symbol value" do
|
389
|
+
DataMapper.repository(:default) do |repos|
|
390
|
+
lambda { Todo.get(2).move(:non_existant_vector_symbol) }.should raise_error(ArgumentError)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
end #/ #move(:non_existant_vector)
|
395
|
+
|
396
|
+
end #/ #move
|
397
|
+
|
398
|
+
describe "#list_scope" do
|
399
|
+
|
400
|
+
describe 'without scope' do
|
401
|
+
class Property
|
402
|
+
include DataMapper::Resource
|
403
|
+
|
404
|
+
property :id, Serial
|
405
|
+
|
406
|
+
is :list
|
407
|
+
end
|
408
|
+
|
409
|
+
before do
|
410
|
+
@property = Property.new
|
411
|
+
end
|
412
|
+
|
413
|
+
it 'should return an empty Hash' do
|
414
|
+
DataMapper.repository(:default) do |repos|
|
415
|
+
@property.list_scope.should == {}
|
416
|
+
end
|
417
|
+
end
|
66
418
|
|
67
|
-
Todo.get(2).position.should == 1
|
68
|
-
Todo.get(1).position.should == 2
|
69
419
|
end
|
70
|
-
end
|
71
420
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
421
|
+
describe 'with scope' do
|
422
|
+
|
423
|
+
it 'should know the scope of the list the item belongs to' do
|
424
|
+
DataMapper.repository(:default) do |repos|
|
425
|
+
Todo.get(1).list_scope.should == {:user_id => @u1.id }
|
426
|
+
end
|
427
|
+
end
|
77
428
|
|
78
|
-
|
79
|
-
Todo.get(3).position.should == 2
|
429
|
+
end
|
80
430
|
|
81
|
-
|
82
|
-
todo.position = 2
|
83
|
-
todo.save
|
431
|
+
end #/ #list_scope
|
84
432
|
|
85
|
-
|
86
|
-
|
433
|
+
describe "#original_list_scope" do
|
434
|
+
|
435
|
+
it "should return a Hash" do
|
436
|
+
Todo.get(2).original_list_scope.class.should == Hash
|
87
437
|
end
|
88
|
-
end
|
89
|
-
end
|
90
438
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
439
|
+
it 'should know the original list scope after the scope changes' do
|
440
|
+
DataMapper.repository(:default) do |repos|
|
441
|
+
item = Todo.get(2)
|
442
|
+
item.user = @u2
|
443
|
+
item.original_list_scope.should == {:user_id => @u1.id }
|
444
|
+
item.original_list_scope.class.should == Hash
|
445
|
+
end
|
98
446
|
end
|
99
|
-
end
|
100
447
|
|
101
|
-
|
102
|
-
repository(:default) do |repos|
|
103
|
-
Todo.get(2).position.should == 2
|
104
|
-
Todo.get(3).position.should == 3
|
105
|
-
Todo.get(2).move :lower
|
106
|
-
Todo.get(2).position.should == 3
|
107
|
-
Todo.get(3).position.should == 2
|
448
|
+
end #/ #original_list_scope
|
108
449
|
|
109
|
-
|
450
|
+
describe "#list_query" do
|
451
|
+
|
452
|
+
it "should return a Hash" do
|
453
|
+
Todo.get(2).list_query.class.should == Hash
|
110
454
|
end
|
111
|
-
end
|
112
455
|
|
113
|
-
|
114
|
-
|
456
|
+
it 'should return a hash with conditions to get the entire list this item belongs to' do
|
457
|
+
DataMapper.repository(:default) do |repos|
|
458
|
+
Todo.get(2).list_query.should == { :user_id => @u1.id, :order => [:position] }
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
end #/ #list_query
|
115
463
|
|
116
|
-
|
117
|
-
Todo.get(1).position.should == 1
|
118
|
-
Todo.get(1).move(:lowest)
|
119
|
-
Todo.get(1).position.should == 3
|
464
|
+
describe "#list" do
|
120
465
|
|
121
|
-
|
122
|
-
Todo.get(
|
123
|
-
Todo.get(
|
124
|
-
Todo.get(
|
125
|
-
Todo.get(5).position.should == 3
|
466
|
+
it "should returns a DataMapper::Collection object" do
|
467
|
+
Todo.get(2).list.class.should == DataMapper::Collection
|
468
|
+
Todo.get(2).list(:user => @u2 ).class.should == DataMapper::Collection
|
469
|
+
Todo.get(2).list(:user_id => nil).class.should == DataMapper::Collection
|
126
470
|
end
|
127
|
-
end
|
128
471
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
472
|
+
it "should return all list items in the current list item's scope" do
|
473
|
+
DataMapper.repository(:default) do |repos|
|
474
|
+
Todo.get(2).list.should == Todo.all(:user => @u1)
|
475
|
+
end
|
476
|
+
end
|
134
477
|
|
135
|
-
|
136
|
-
|
478
|
+
it "should return all items in the specified scope" do
|
479
|
+
DataMapper.repository(:default) do |repos|
|
480
|
+
Todo.get(2).list(:user => @u2 ).should == Todo.all(:user => @u2)
|
481
|
+
end
|
137
482
|
end
|
138
|
-
end
|
139
483
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
484
|
+
end #/ #list
|
485
|
+
|
486
|
+
describe "#repair_list" do
|
487
|
+
|
488
|
+
it 'should repair the list positions after a manually updated position' do
|
489
|
+
DataMapper.repository(:default) do |repos|
|
490
|
+
item = Todo.get(5)
|
491
|
+
item.update(:position => 20)
|
492
|
+
item.position.should == 20
|
493
|
+
|
494
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 20] ]
|
495
|
+
|
496
|
+
item = Todo.get(5)
|
497
|
+
item.repair_list
|
498
|
+
item.position.should == 5
|
499
|
+
end
|
147
500
|
end
|
148
|
-
end
|
149
|
-
end
|
150
501
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
502
|
+
it 'should repair the list positions in a really messed up list while retaining the order' do
|
503
|
+
DataMapper.repository(:default) do |repos|
|
504
|
+
# need to set these fixed in order to test the outcome
|
505
|
+
new_positions = [ 83, 5, 186, 48, 99 ]
|
506
|
+
Todo.all.each do |item|
|
507
|
+
item.update(:position => new_positions[item.id-1] )
|
508
|
+
end
|
509
|
+
# note the order of item id's
|
510
|
+
todo_list.should == [ [2, 5], [4, 48], [1, 83], [5, 99], [3, 186] ]
|
158
511
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
512
|
+
item = Todo.get(5)
|
513
|
+
item.repair_list
|
514
|
+
# note position numbers being 1 - 5, and it retained the id positions
|
515
|
+
todo_list.should == [ [2, 1], [4, 2], [1, 3], [5, 4], [3, 5] ]
|
516
|
+
end
|
517
|
+
end
|
163
518
|
|
164
|
-
|
165
|
-
item.position = 1
|
166
|
-
item.save
|
519
|
+
end #/ #repair_list
|
167
520
|
|
168
|
-
|
169
|
-
Todo.get(5).position.should == 2
|
521
|
+
describe "#reorder_list" do
|
170
522
|
|
523
|
+
before do
|
524
|
+
@u3 = User.create(:name => 'Eve')
|
525
|
+
@todo_1 = Todo.create(:user => @u3, :title => "Clean the house")
|
526
|
+
@todo_2 = Todo.create(:user => @u3, :title => "Brush the dogs")
|
527
|
+
@todo_3 = Todo.create(:user => @u3, :title => "Arrange bookshelf")
|
171
528
|
end
|
172
|
-
end
|
173
529
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
530
|
+
it "should reorder the list based on the order options given" do
|
531
|
+
DataMapper.repository(:default) do |repos|
|
532
|
+
todo_list(:user => @u3).should == [ [9, 1], [10, 2], [11, 3] ]
|
533
|
+
@todo_1.reorder_list([:title.asc]).should == true
|
534
|
+
todo_list(:user => @u3).should == [ [11, 1], [10, 2], [9, 3] ]
|
535
|
+
|
536
|
+
@todo_1.reorder_list([:title.desc]).should == true
|
537
|
+
todo_list(:user => @u3).should == [ [9, 1], [10, 2], [11, 3] ]
|
538
|
+
end
|
179
539
|
end
|
180
|
-
end
|
181
540
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
541
|
+
end #/ #reorder_list
|
542
|
+
|
543
|
+
describe "#detach" do
|
544
|
+
|
545
|
+
it 'should detach from list and retain scope' do
|
546
|
+
DataMapper.repository(:default) do |repos|
|
547
|
+
item = Todo.get(2)
|
548
|
+
item.position.should == 2
|
549
|
+
item.user.should == @u1
|
188
550
|
|
189
|
-
|
551
|
+
item.detach
|
190
552
|
|
553
|
+
item.original_list_scope.should == { :user_id => @u1.id }
|
554
|
+
item.list_scope.should == { :user_id => @u1.id }
|
555
|
+
# item.list_scope.should != item.original_list_scope # FAIL. accepts both != and ==
|
556
|
+
item.position.should == nil
|
557
|
+
|
558
|
+
todo_list.should == [[1, 1], [2,nil], [3, 2], [4, 3], [5, 4]]
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
it 'should detach from list and change scope' do
|
563
|
+
DataMapper.repository(:default) do |repos|
|
564
|
+
item = Todo.get(2)
|
565
|
+
item.position.should == 2
|
566
|
+
item.user.should == @u1
|
567
|
+
|
568
|
+
item.detach(:user_id => 1)
|
569
|
+
|
570
|
+
item.original_list_scope.should == { :user_id => @u1.id }
|
571
|
+
item.list_scope.should == { :user_id => @u1.id }
|
572
|
+
# item.list_scope.should != item.original_list_scope # FAIL. accepts both != and ==
|
573
|
+
item.position.should == nil
|
574
|
+
|
575
|
+
todo_list.should == [[1, 1], [2,nil], [3, 2], [4, 3], [5, 4]]
|
576
|
+
end
|
191
577
|
end
|
578
|
+
|
579
|
+
end #/ #detach
|
580
|
+
|
581
|
+
describe "#move_to_list" do
|
582
|
+
|
583
|
+
it "should move an item from one list to the bottom of another list" do
|
584
|
+
DataMapper.repository(:default) do |repos|
|
585
|
+
item = Todo.get(2)
|
586
|
+
list_scope = Todo.get(6).list_scope
|
587
|
+
list_scope.should == { :user_id => @u2.id }
|
588
|
+
|
589
|
+
item.move_to_list(@u2.id)
|
590
|
+
# equivalent of:
|
591
|
+
# item.detach
|
592
|
+
# item.user = @u2
|
593
|
+
# item.save
|
594
|
+
# item.reload
|
595
|
+
|
596
|
+
todo_list(:user => @u1).should == [ [1, 1], [3, 2], [4, 3], [5, 4] ]
|
597
|
+
|
598
|
+
todo_list(:user => @u2).should == [ [6, 1], [7, 2], [8, 3], [2, 4] ]
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
it "should move an item from one list to a fixed position in another list" do
|
603
|
+
pending %Q{Failing Test: Error = [ no such table: todos ]. Error is due to the nested transactions. (See notes in spec)}
|
604
|
+
# NOTE:: This error happens because of the nested transactions taking place
|
605
|
+
# first within the #move_to_list and then the #move method.
|
606
|
+
# If you comment out either of those transactions, the test passes.
|
607
|
+
|
608
|
+
DataMapper.repository(:default) do |repos|
|
609
|
+
item = Todo.get(2)
|
610
|
+
list_scope = Todo.get(6).list_scope
|
611
|
+
list_scope.should == { :user_id => @u2.id }
|
612
|
+
|
613
|
+
item.move_to_list(@u2.id, 3)
|
614
|
+
|
615
|
+
todo_list(:user => @u1).should == [ [1, 1], [3, 2], [4, 3], [5, 4] ]
|
616
|
+
|
617
|
+
todo_list(:user => @u2).should == [ [6, 1], [7, 2], [2, 3], [8, 4] ]
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
end #/ #move_to_list
|
622
|
+
|
623
|
+
describe "#left_sibling (alias #higher_item or #previous_item)" do
|
624
|
+
|
625
|
+
it "should return the higher item in list" do
|
626
|
+
DataMapper.repository(:default) do |repos|
|
627
|
+
item = Todo.get(2)
|
628
|
+
item.left_sibling.should == Todo.get(1)
|
629
|
+
item.higher_item.should == Todo.get(1)
|
630
|
+
item.previous_item.should == Todo.get(1)
|
631
|
+
end
|
632
|
+
end
|
633
|
+
|
634
|
+
it "should return nil when there's NO higher item" do
|
635
|
+
DataMapper.repository(:default) do |repos|
|
636
|
+
item = Todo.get(1)
|
637
|
+
item.left_sibling.should == nil
|
638
|
+
item.higher_item.should == nil
|
639
|
+
item.previous_item.should == nil
|
640
|
+
end
|
641
|
+
end
|
642
|
+
|
643
|
+
end #/ #left_sibling (alias #higher_item)
|
644
|
+
|
645
|
+
describe "#right_sibling (alias #lower_item or #next_item)" do
|
646
|
+
|
647
|
+
it "should return the lower item in list" do
|
648
|
+
DataMapper.repository(:default) do |repos|
|
649
|
+
item = Todo.get(2)
|
650
|
+
item.right_sibling.should == Todo.get(3)
|
651
|
+
item.lower_item.should == Todo.get(3)
|
652
|
+
item.next_item.should == Todo.get(3)
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
it "should return nil when there's NO lower item" do
|
657
|
+
DataMapper.repository(:default) do |repos|
|
658
|
+
item = Todo.get(5)
|
659
|
+
item.right_sibling.should == nil
|
660
|
+
item.lower_item.should == nil
|
661
|
+
item.next_item.should == nil
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
end #/ #right_sibling (alias #lower_item)
|
666
|
+
|
667
|
+
end #/ Instance Methods
|
668
|
+
|
669
|
+
describe "Workflows" do
|
670
|
+
|
671
|
+
describe "CRUD" do
|
672
|
+
|
673
|
+
# describe "#create" do
|
674
|
+
# pending
|
675
|
+
# end #/ #create
|
676
|
+
|
677
|
+
describe "Updating list items" do
|
678
|
+
|
679
|
+
it "should NOT loose position when updating other attributes" do
|
680
|
+
DataMapper.repository(:default) do |repos|
|
681
|
+
item = Todo.get(2)
|
682
|
+
item.position.should == 2
|
683
|
+
item.user.should == @u1
|
684
|
+
|
685
|
+
item.update(:title => "Updated")
|
686
|
+
|
687
|
+
item = Todo.get(2)
|
688
|
+
item.position.should == 2
|
689
|
+
item.title.should == 'Updated'
|
690
|
+
item.user.should == @u1
|
691
|
+
end
|
692
|
+
end
|
693
|
+
|
694
|
+
end #/ Updating list items
|
695
|
+
|
696
|
+
describe "Deleting items" do
|
697
|
+
|
698
|
+
describe "using #destroy" do
|
699
|
+
|
700
|
+
it 'should remove from list and old list should automatically repair positions' do
|
701
|
+
DataMapper.repository(:default) do |repos|
|
702
|
+
todo_list.should == [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
703
|
+
Todo.get(2).destroy.should == true
|
704
|
+
todo_list.should == [[1, 1], [3, 2], [4, 3], [5, 4] ]
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
708
|
+
end #/ using #destroy
|
709
|
+
|
710
|
+
describe "using #destroy!" do
|
711
|
+
|
712
|
+
it 'should remove from list and old list does NOT automatically repair positions' do
|
713
|
+
DataMapper.repository(:default) do |repos|
|
714
|
+
todo_list.should == [[1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
715
|
+
Todo.get(2).destroy!.should == true
|
716
|
+
todo_list.should == [[1, 1], [3, 3], [4, 4], [5, 5] ]
|
717
|
+
end
|
718
|
+
end
|
719
|
+
|
720
|
+
end #/ using #destroy!
|
721
|
+
|
722
|
+
end #/ Deleting items
|
723
|
+
|
724
|
+
end #/ CRUD
|
725
|
+
|
726
|
+
describe 'Automatic positioning' do
|
727
|
+
|
728
|
+
it 'should get the shadow variable of the last position' do
|
729
|
+
DataMapper.repository do
|
730
|
+
Todo.get(3).position = 8
|
731
|
+
Todo.get(3).should be_dirty
|
732
|
+
Todo.get(3).attribute_dirty?(:position).should == true
|
733
|
+
Todo.get(3).original_attributes[ Todo.properties[:position] ].should == 3
|
734
|
+
Todo.get(3).list_scope.should == Todo.get(3).original_list_scope
|
735
|
+
end
|
736
|
+
end
|
737
|
+
|
738
|
+
it 'should insert items into the list automatically on create' do
|
739
|
+
DataMapper.repository(:default) do |repos|
|
740
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
741
|
+
todo_list(:user => @u2).should == [ [6, 1], [7, 2], [8, 3] ]
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
end # automatic positioning
|
746
|
+
|
747
|
+
describe "Manual Positioning" do
|
748
|
+
# NOTE:: The positions in the list does NOT change automatically when an item is given
|
749
|
+
# a position via this syntax:
|
750
|
+
#
|
751
|
+
# item.position = 4
|
752
|
+
# item.save
|
753
|
+
#
|
754
|
+
# Enabling this functionality (re-shuffling list on update) causes a lot of extra SQL queries
|
755
|
+
# and ultimately still get the list order wrong when doing a batch update.
|
756
|
+
#
|
757
|
+
# This 'breaks' the common assumption of updating an item variable, but I think it's a worthwhile break
|
758
|
+
|
759
|
+
it 'should NOT rearrange items when setting position manually' do
|
760
|
+
DataMapper.repository(:default) do |repos|
|
761
|
+
item = Todo.get(2)
|
762
|
+
item.position = 1
|
763
|
+
item.save
|
764
|
+
|
765
|
+
todo_list.should == [ [1, 1], [2, 1], [3, 3], [4, 4], [5, 5] ] # note, the two items with 1 as position
|
766
|
+
|
767
|
+
item.update(:position => 3)
|
768
|
+
todo_list.should == [ [1, 1], [2, 3], [3, 3], [4, 4], [5, 5] ] # note, the two items with 3 as position
|
769
|
+
end
|
770
|
+
end
|
771
|
+
|
772
|
+
it 'should NOT rearrange items when setting position manually via update()' do
|
773
|
+
DataMapper.repository(:default) do |repos|
|
774
|
+
item = Todo.get(2)
|
775
|
+
item.update(:position => 1)
|
776
|
+
|
777
|
+
todo_list.should == [ [1, 1], [2, 1], [3, 3], [4, 4], [5, 5] ] # note, the two items with 1 as position
|
778
|
+
|
779
|
+
item.update(:position => 3)
|
780
|
+
todo_list.should == [ [1, 1], [2, 3], [3, 3], [4, 4], [5, 5] ] # note, the two items with 3 as position
|
781
|
+
end
|
782
|
+
|
783
|
+
end
|
784
|
+
|
785
|
+
end #/ Manual Positioning
|
786
|
+
|
787
|
+
|
788
|
+
describe "Batch change item positions" do
|
789
|
+
|
790
|
+
describe "when using item.position = N syntax " do
|
791
|
+
|
792
|
+
it "should reverse the list" do
|
793
|
+
DataMapper.repository(:default) do |repos|
|
794
|
+
items = Todo.all(:user => @u1, :order => [:position])
|
795
|
+
items.each{ |item| item.update(:position => [5,4,3,2,1].index(item.id) + 1) }
|
796
|
+
todo_list.should == [ [5,1], [4,2], [3,3], [2,4], [1,5] ]
|
797
|
+
end
|
798
|
+
end
|
799
|
+
|
800
|
+
it "should move the first item to last in list" do
|
801
|
+
DataMapper.repository(:default) do |repos|
|
802
|
+
items = Todo.all(:user => @u1, :order => [:position])
|
803
|
+
|
804
|
+
items.each{ |item| item.update(:position => [2,3,4,5,1].index(item.id) + 1) }
|
805
|
+
|
806
|
+
todo_list.should == [ [2,1], [3,2], [4,3], [5,4], [1,5] ]
|
807
|
+
end
|
808
|
+
end
|
809
|
+
|
810
|
+
it "should randomly move items around in the list" do
|
811
|
+
DataMapper.repository(:default) do |repos|
|
812
|
+
items = Todo.all(:user => @u1, :order => [:position])
|
813
|
+
|
814
|
+
items.each{ |item| item.update(:position => [5,2,4,3,1].index(item.id) + 1) }
|
815
|
+
|
816
|
+
todo_list.should == [ [5,1], [2,2], [4,3], [3,4], [1,5] ]
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
end #/ when using item.position = N syntax
|
821
|
+
|
822
|
+
describe "when using item.move(N) syntax => [NB! create more SQL queries]" do
|
823
|
+
|
824
|
+
it "should reverse the list => [NB! creates 5x the number of SQL queries]" do
|
825
|
+
DataMapper.repository(:default) do |repos|
|
826
|
+
items = Todo.all(:user => @u1, :order => [:position])
|
827
|
+
|
828
|
+
items.each{ |item| item.move([5,4,3,2,1].index(item.id) + 1) }
|
829
|
+
|
830
|
+
todo_list.should == [ [5,1], [4,2], [3,3], [2,4], [1,5] ]
|
831
|
+
end
|
832
|
+
end
|
833
|
+
|
834
|
+
it "should move the first item to last in list" do
|
835
|
+
DataMapper.repository(:default) do |repos|
|
836
|
+
items = Todo.all(:user => @u1, :order => [:position])
|
837
|
+
|
838
|
+
items.each{ |item| item.move([2,3,4,5,1].index(item.id) + 1) }
|
839
|
+
|
840
|
+
todo_list.should == [ [2,1], [3,2], [4,3], [5,4], [1,5] ]
|
841
|
+
end
|
842
|
+
end
|
843
|
+
|
844
|
+
it "should randomly move items around in the list" do
|
845
|
+
DataMapper.repository(:default) do |repos|
|
846
|
+
items = Todo.all(:user => @u1, :order => [:position])
|
847
|
+
|
848
|
+
items.each{ |item| item.move([5,2,4,3,1].index(item.id) + 1) }
|
849
|
+
|
850
|
+
todo_list.should == [ [5,1], [2,2], [4,3], [3,4], [1,5] ]
|
851
|
+
end
|
852
|
+
end
|
853
|
+
|
854
|
+
end #/ when using item.move(N) syntax
|
855
|
+
|
856
|
+
end #/ Re-ordering
|
857
|
+
|
858
|
+
describe "Movements" do
|
859
|
+
|
860
|
+
it "see the Instance Methods > #move specs above" do
|
861
|
+
# NOTE:: keeping this in the specs since this group was here previously, but it's now redundant.
|
862
|
+
# Should the tests be shared and used twice ?
|
863
|
+
true.should == true
|
864
|
+
end
|
865
|
+
|
866
|
+
end #/ Movements
|
867
|
+
|
868
|
+
describe "Scoping" do
|
869
|
+
|
870
|
+
it 'should detach from old list if scope is changed and retain position in new list' do
|
871
|
+
DataMapper.repository(:default) do |repos|
|
872
|
+
item = Todo.get(2)
|
873
|
+
item.position.should == 2
|
874
|
+
item.user.should == @u1
|
875
|
+
|
876
|
+
item.user = @u2
|
877
|
+
item.save
|
878
|
+
|
879
|
+
item.list_scope.should != item.original_list_scope
|
880
|
+
item.list_scope.should == { :user_id => @u2.id }
|
881
|
+
item.position.should == 2
|
882
|
+
|
883
|
+
todo_list.should == [[1, 1], [3, 2], [4, 3], [5, 4]]
|
884
|
+
|
885
|
+
todo_list(:user => @u2).should == [[6, 1], [2, 2], [7, 3], [8, 4]]
|
886
|
+
end
|
887
|
+
end
|
888
|
+
|
889
|
+
it 'should detach from old list if scope is changed and given bottom position in new list if position is empty' do
|
890
|
+
DataMapper.repository(:default) do |repos|
|
891
|
+
item = Todo.get(2)
|
892
|
+
item.position.should == 2
|
893
|
+
item.user.should == @u1
|
894
|
+
|
895
|
+
item.position = nil # NOTE:: Creates a messed up original list.
|
896
|
+
item.user = @u2
|
897
|
+
item.save
|
898
|
+
|
899
|
+
item.list_scope.should != item.original_list_scope
|
900
|
+
item.list_scope.should == { :user_id => @u2.id }
|
901
|
+
item.position.should == 4
|
902
|
+
|
903
|
+
todo_list.should == [ [1, 1], [3, 3], [4, 4], [5, 5] ] # messed up
|
904
|
+
|
905
|
+
todo_list(:user => @u2).should == [ [6, 1], [7, 2], [8, 3], [2, 4] ]
|
906
|
+
end
|
907
|
+
end
|
908
|
+
|
909
|
+
describe "when deleting item" do
|
910
|
+
# see Workflows > CRUD > Deleting items
|
911
|
+
end #/ when deleting item
|
912
|
+
|
913
|
+
end #/ Scoping
|
914
|
+
|
915
|
+
describe "STI inheritance" do
|
916
|
+
|
917
|
+
it "should have some tests" do
|
918
|
+
pending
|
919
|
+
end
|
920
|
+
|
921
|
+
end #/ STI inheritance
|
922
|
+
|
923
|
+
end #/ Workflows
|
924
|
+
|
925
|
+
|
926
|
+
describe "Twilight Zone" do
|
927
|
+
|
928
|
+
# NOTE:: I do not understand the reasons for this behaviour, but perhaps it's how it should be.
|
929
|
+
# Why does having two variables pointing to the same row prevent it from being updated ?
|
930
|
+
#
|
931
|
+
describe "accessing the same object via two variables" do
|
932
|
+
|
933
|
+
before do
|
934
|
+
@todo5 = Todo.get(5)
|
935
|
+
end
|
936
|
+
|
937
|
+
it "should NOT update list" do
|
938
|
+
DataMapper.repository(:default) do |repos|
|
939
|
+
item = Todo.get(5)
|
940
|
+
item.position.should == 5
|
941
|
+
item.position.should == @todo5.position
|
942
|
+
|
943
|
+
@todo5.update(:position => 20) # this should update the position in the DB
|
944
|
+
|
945
|
+
@todo5.position.should == 20
|
946
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
947
|
+
|
948
|
+
item.position.should == 5
|
949
|
+
end
|
950
|
+
end
|
951
|
+
|
952
|
+
it "should update list when doing item.reload" do
|
953
|
+
DataMapper.repository(:default) do |repos|
|
954
|
+
item = Todo.get(5)
|
955
|
+
item.position.should == 5
|
956
|
+
item.position.should == @todo5.position
|
957
|
+
|
958
|
+
@todo5.update(:position => 20) # this should update the position in the DB
|
959
|
+
|
960
|
+
@todo5.position.should == 20
|
961
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5] ]
|
962
|
+
|
963
|
+
item.reload
|
964
|
+
item.position.should == 20
|
965
|
+
|
966
|
+
todo_list.should == [ [1, 1], [2, 2], [3, 3], [4, 4], [5, 20] ]
|
967
|
+
end
|
968
|
+
end
|
969
|
+
|
970
|
+
end #/ accessing the same object via two variables
|
971
|
+
|
972
|
+
end #/ Twilight Zone
|
973
|
+
|
974
|
+
|
975
|
+
describe "With :unique_index => position defined" do
|
976
|
+
|
977
|
+
class Client
|
978
|
+
include DataMapper::Resource
|
979
|
+
|
980
|
+
property :id, Serial
|
981
|
+
property :name, String
|
982
|
+
|
983
|
+
has n, :client_todos
|
192
984
|
end
|
193
|
-
end
|
194
985
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
986
|
+
class ClientTodo
|
987
|
+
include DataMapper::Resource
|
988
|
+
|
989
|
+
property :id, Serial
|
990
|
+
property :title, String
|
991
|
+
property :position, Integer, :nullable => false, :unique_index => :position
|
992
|
+
property :client_id, Integer, :unique_index => :position
|
993
|
+
|
994
|
+
belongs_to :client
|
995
|
+
|
996
|
+
is :list, :scope => [:client_id]
|
997
|
+
end
|
201
998
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
999
|
+
before :each do
|
1000
|
+
Client.auto_migrate!
|
1001
|
+
ClientTodo.auto_migrate!
|
1002
|
+
|
1003
|
+
@u1 = Client.create(:name => 'Johnny')
|
1004
|
+
@u2 = Client.create(:name => 'Freddy')
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
before(:each) do
|
1008
|
+
@loop = 20
|
1009
|
+
@loop.times do |n|
|
1010
|
+
ClientTodo.create(:client => @u1, :title => "ClientTodo #{n+1}" )
|
206
1011
|
end
|
207
1012
|
end
|
208
|
-
|
1013
|
+
|
1014
|
+
describe "should handle :unique_index => :position" do
|
1015
|
+
|
1016
|
+
it "should generate all in the correct order" do
|
1017
|
+
DataMapper.repository(:default) do |repos|
|
1018
|
+
ClientTodo.all.map{ |a| [a.id, a.position] }.should == (1..@loop).map { |n| [n,n] }
|
1019
|
+
end
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
it "should move items :higher in list" do
|
1023
|
+
pending "Failing Test: Error = [ columns position, client_id are not unique ] (See notes in spec)"
|
1024
|
+
# NOTE:: This error happens because of the :unique_index => position setting.
|
1025
|
+
# Most likely the reason is due to the order of updates to the position attribute in the DB is NOT
|
1026
|
+
# fully consistant, and clashes therefore occur.
|
1027
|
+
# This could be solved(?) with adding an 'ORDER BY position' in the SQL for MySQL, but won't work with SQLite3
|
1028
|
+
#
|
1029
|
+
# Commenting out :unique_index => :position in the ClientTodo model enables the tests to pass.
|
1030
|
+
|
1031
|
+
DataMapper.repository(:default) do |repos|
|
1032
|
+
ClientTodo.get(2).move(:higher).should == true
|
1033
|
+
ClientTodo.all.map{ |a| [a.id, a.position] }.should == [ [1, 2], [2, 1] ] + (3..@loop).map { |n| [n,n] }
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
it "should move items :lower in list" do
|
1038
|
+
pending "Failing Test: Error = [ columns position, client_id are not unique ] (See notes in spec)"
|
1039
|
+
DataMapper.repository(:default) do |repos|
|
1040
|
+
ClientTodo.get(9).move(:lower).should == true
|
1041
|
+
ClientTodo.all.map{ |a| [a.id, a.position] }.should == (1..8).map { |n| [n,n] } + [ [9, 10], [10, 9] ] + (11..@loop).map { |n| [n,n] }
|
1042
|
+
end
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
end #/ should handle :unique_index => :position
|
1046
|
+
|
1047
|
+
end #/ With :unique_index => position defined
|
1048
|
+
|
209
1049
|
|
210
1050
|
end
|
1051
|
+
|
211
1052
|
end
|