acts_as_list 0.1.4 → 0.2.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/.gitignore +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +2 -0
- data/README.md +103 -0
- data/Rakefile +1 -3
- data/acts_as_list.gemspec +2 -2
- data/init.rb +2 -0
- data/lib/acts_as_list/active_record/acts/list.rb +179 -36
- data/lib/acts_as_list/version.rb +1 -1
- data/lib/acts_as_list.rb +23 -1
- data/test/helper.rb +2 -0
- data/test/shared.rb +8 -0
- data/test/shared_array_scope_list.rb +160 -0
- data/test/shared_list.rb +230 -0
- data/test/shared_list_sub.rb +122 -0
- data/test/shared_top_addition.rb +87 -0
- data/test/shared_zero_based.rb +86 -0
- data/test/test_list.rb +291 -465
- metadata +32 -23
- data/README.rdoc +0 -35
data/test/test_list.rb
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# NOTE: following now done in helper.rb (better Readability)
|
|
2
|
-
require 'helper
|
|
2
|
+
require 'helper'
|
|
3
3
|
|
|
4
4
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
|
5
|
+
ActiveRecord::Schema.verbose = false
|
|
5
6
|
|
|
6
|
-
def setup_db
|
|
7
|
+
def setup_db(position_options = {})
|
|
8
|
+
# AR caches columns options like defaults etc. Clear them!
|
|
9
|
+
ActiveRecord::Base.connection.schema_cache.clear!
|
|
7
10
|
ActiveRecord::Schema.define(:version => 1) do
|
|
8
11
|
create_table :mixins do |t|
|
|
9
|
-
t.column :pos, :integer
|
|
12
|
+
t.column :pos, :integer, position_options
|
|
13
|
+
t.column :active, :boolean, :default => true
|
|
10
14
|
t.column :parent_id, :integer
|
|
11
15
|
t.column :parent_type, :string
|
|
12
16
|
t.column :created_at, :datetime
|
|
@@ -15,6 +19,10 @@ def setup_db
|
|
|
15
19
|
end
|
|
16
20
|
end
|
|
17
21
|
|
|
22
|
+
def setup_db_with_default
|
|
23
|
+
setup_db :default => 0
|
|
24
|
+
end
|
|
25
|
+
|
|
18
26
|
# Returns true if ActiveRecord is rails3 version
|
|
19
27
|
def rails_3
|
|
20
28
|
defined?(ActiveRecord::VERSION) && ActiveRecord::VERSION::MAJOR >= 3
|
|
@@ -27,624 +35,442 @@ def teardown_db
|
|
|
27
35
|
end
|
|
28
36
|
|
|
29
37
|
class Mixin < ActiveRecord::Base
|
|
38
|
+
self.table_name = 'mixins'
|
|
39
|
+
attr_accessible :active, :parent_id, :parent_type
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class ProtectedMixin < ActiveRecord::Base
|
|
43
|
+
self.table_name = 'mixins'
|
|
44
|
+
attr_protected :active
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class ProtectedListMixin < ProtectedMixin
|
|
48
|
+
acts_as_list :column => "pos"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class UnProtectedMixin < ActiveRecord::Base
|
|
52
|
+
self.table_name = 'mixins'
|
|
30
53
|
end
|
|
31
54
|
|
|
55
|
+
class UnProtectedListMixin < UnProtectedMixin
|
|
56
|
+
acts_as_list :column => "pos"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
|
|
32
60
|
class ListMixin < Mixin
|
|
33
61
|
acts_as_list :column => "pos", :scope => :parent
|
|
34
|
-
|
|
35
|
-
def self.table_name() "mixins" end
|
|
36
62
|
end
|
|
37
63
|
|
|
38
64
|
class ListMixinSub1 < ListMixin
|
|
39
65
|
end
|
|
40
66
|
|
|
41
67
|
class ListMixinSub2 < ListMixin
|
|
68
|
+
if rails_3
|
|
69
|
+
validates :pos, :presence => true
|
|
70
|
+
else
|
|
71
|
+
validates_presence_of :pos
|
|
72
|
+
end
|
|
42
73
|
end
|
|
43
74
|
|
|
44
|
-
class ListWithStringScopeMixin <
|
|
75
|
+
class ListWithStringScopeMixin < Mixin
|
|
45
76
|
acts_as_list :column => "pos", :scope => 'parent_id = #{parent_id}'
|
|
46
|
-
|
|
47
|
-
def self.table_name() "mixins" end
|
|
48
77
|
end
|
|
49
78
|
|
|
50
79
|
class ArrayScopeListMixin < Mixin
|
|
51
80
|
acts_as_list :column => "pos", :scope => [:parent_id, :parent_type]
|
|
52
|
-
|
|
53
|
-
def self.table_name() "mixins" end
|
|
54
81
|
end
|
|
55
82
|
|
|
56
|
-
class ZeroBasedMixin <
|
|
83
|
+
class ZeroBasedMixin < Mixin
|
|
57
84
|
acts_as_list :column => "pos", :top_of_list => 0, :scope => [:parent_id]
|
|
85
|
+
end
|
|
58
86
|
|
|
59
|
-
|
|
87
|
+
class DefaultScopedMixin < Mixin
|
|
88
|
+
acts_as_list :column => "pos"
|
|
89
|
+
default_scope { order('pos ASC') }
|
|
60
90
|
end
|
|
61
91
|
|
|
92
|
+
class DefaultScopedWhereMixin < Mixin
|
|
93
|
+
acts_as_list :column => "pos"
|
|
94
|
+
default_scope { order('pos ASC').where(:active => true) }
|
|
95
|
+
end
|
|
62
96
|
|
|
63
|
-
class
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
97
|
+
class TopAdditionMixin < Mixin
|
|
98
|
+
acts_as_list :column => "pos", :add_new_at => :top, :scope => :parent_id
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class ActsAsListTestCase < Test::Unit::TestCase
|
|
102
|
+
# No default test required a this class is abstract.
|
|
103
|
+
# Need for test/unit.
|
|
104
|
+
undef_method :default_test if method_defined?(:default_test)
|
|
68
105
|
|
|
69
106
|
def teardown
|
|
70
107
|
teardown_db
|
|
71
108
|
end
|
|
109
|
+
end
|
|
72
110
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
assert_equal 0, new.pos
|
|
76
|
-
assert new.first?
|
|
77
|
-
assert new.last?
|
|
78
|
-
|
|
79
|
-
new = ZeroBasedMixin.create(:parent_id => 20)
|
|
80
|
-
assert_equal 1, new.pos
|
|
81
|
-
assert !new.first?
|
|
82
|
-
assert new.last?
|
|
83
|
-
|
|
84
|
-
new = ZeroBasedMixin.create(:parent_id => 20)
|
|
85
|
-
assert_equal 2, new.pos
|
|
86
|
-
assert !new.first?
|
|
87
|
-
assert new.last?
|
|
111
|
+
class ZeroBasedTest < ActsAsListTestCase
|
|
112
|
+
include Shared::ZeroBased
|
|
88
113
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
assert new.last?
|
|
114
|
+
def setup
|
|
115
|
+
setup_db
|
|
116
|
+
super
|
|
93
117
|
end
|
|
118
|
+
end
|
|
94
119
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
ListMixin.find(2).move_lower
|
|
99
|
-
assert_equal [1, 3, 2, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
100
|
-
|
|
101
|
-
ListMixin.find(2).move_higher
|
|
102
|
-
assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
103
|
-
|
|
104
|
-
ListMixin.find(1).move_to_bottom
|
|
105
|
-
assert_equal [2, 3, 4, 1], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
106
|
-
|
|
107
|
-
ListMixin.find(1).move_to_top
|
|
108
|
-
assert_equal [1, 2, 3, 4], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
109
|
-
|
|
110
|
-
ListMixin.find(2).move_to_bottom
|
|
111
|
-
assert_equal [1, 3, 4, 2], ZeroBasedMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
120
|
+
class ZeroBasedTestWithDefault < ActsAsListTestCase
|
|
121
|
+
include Shared::ZeroBased
|
|
112
122
|
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
def setup
|
|
124
|
+
setup_db_with_default
|
|
125
|
+
super
|
|
115
126
|
end
|
|
127
|
+
end
|
|
116
128
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
assert_equal 0, new.pos
|
|
120
|
-
|
|
121
|
-
new = ZeroBasedMixin.create(:parent_id => 20)
|
|
122
|
-
assert_equal 1, new.pos
|
|
123
|
-
|
|
124
|
-
new = ZeroBasedMixin.create(:parent_id => 20)
|
|
125
|
-
assert_equal 2, new.pos
|
|
126
|
-
|
|
127
|
-
new4 = ZeroBasedMixin.create(:parent_id => 20)
|
|
128
|
-
assert_equal 3, new4.pos
|
|
129
|
-
|
|
130
|
-
new4.insert_at(2)
|
|
131
|
-
assert_equal 2, new4.pos
|
|
132
|
-
|
|
133
|
-
new.reload
|
|
134
|
-
assert_equal 3, new.pos
|
|
135
|
-
|
|
136
|
-
new.insert_at(2)
|
|
137
|
-
assert_equal 2, new.pos
|
|
129
|
+
class ListTest < ActsAsListTestCase
|
|
130
|
+
include Shared::List
|
|
138
131
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
132
|
+
def setup
|
|
133
|
+
setup_db
|
|
134
|
+
super
|
|
135
|
+
end
|
|
136
|
+
end
|
|
144
137
|
|
|
145
|
-
|
|
146
|
-
|
|
138
|
+
class ListTestWithDefault < ActsAsListTestCase
|
|
139
|
+
include Shared::List
|
|
147
140
|
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
def setup
|
|
142
|
+
setup_db_with_default
|
|
143
|
+
super
|
|
150
144
|
end
|
|
151
|
-
|
|
152
145
|
end
|
|
153
146
|
|
|
154
|
-
|
|
155
|
-
|
|
147
|
+
class ListSubTest < ActsAsListTestCase
|
|
148
|
+
include Shared::ListSub
|
|
156
149
|
|
|
157
150
|
def setup
|
|
158
151
|
setup_db
|
|
159
|
-
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def teardown
|
|
163
|
-
teardown_db
|
|
152
|
+
super
|
|
164
153
|
end
|
|
154
|
+
end
|
|
165
155
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
ListMixin.find(2).move_lower
|
|
170
|
-
assert_equal [1, 3, 2, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
171
|
-
|
|
172
|
-
ListMixin.find(2).move_higher
|
|
173
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
174
|
-
|
|
175
|
-
ListMixin.find(1).move_to_bottom
|
|
176
|
-
assert_equal [2, 3, 4, 1], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
156
|
+
class ListSubTestWithDefault < ActsAsListTestCase
|
|
157
|
+
include Shared::ListSub
|
|
177
158
|
|
|
178
|
-
|
|
179
|
-
|
|
159
|
+
def setup
|
|
160
|
+
setup_db_with_default
|
|
161
|
+
super
|
|
162
|
+
end
|
|
163
|
+
end
|
|
180
164
|
|
|
181
|
-
|
|
182
|
-
|
|
165
|
+
class ArrayScopeListTest < ActsAsListTestCase
|
|
166
|
+
include Shared::ArrayScopeList
|
|
183
167
|
|
|
184
|
-
|
|
185
|
-
|
|
168
|
+
def setup
|
|
169
|
+
setup_db
|
|
170
|
+
super
|
|
186
171
|
end
|
|
172
|
+
end
|
|
187
173
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
ListMixin.find(3).move_to_bottom
|
|
191
|
-
assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
192
|
-
end
|
|
174
|
+
class ArrayScopeListTestWithDefault < ActsAsListTestCase
|
|
175
|
+
include Shared::ArrayScopeList
|
|
193
176
|
|
|
194
|
-
def
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
|
|
198
|
-
assert_nil ListMixin.find(4).lower_item
|
|
177
|
+
def setup
|
|
178
|
+
setup_db_with_default
|
|
179
|
+
super
|
|
199
180
|
end
|
|
181
|
+
end
|
|
200
182
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
183
|
+
class DefaultScopedTest < ActsAsListTestCase
|
|
184
|
+
def setup
|
|
185
|
+
setup_db
|
|
186
|
+
(1..4).each { |counter| DefaultScopedMixin.create!({:pos => counter}) }
|
|
205
187
|
end
|
|
206
188
|
|
|
207
189
|
def test_insert
|
|
208
|
-
new =
|
|
209
|
-
assert_equal
|
|
210
|
-
assert new.first?
|
|
190
|
+
new = DefaultScopedMixin.create
|
|
191
|
+
assert_equal 5, new.pos
|
|
192
|
+
assert !new.first?
|
|
211
193
|
assert new.last?
|
|
212
194
|
|
|
213
|
-
new =
|
|
214
|
-
assert_equal
|
|
195
|
+
new = DefaultScopedMixin.create
|
|
196
|
+
assert_equal 6, new.pos
|
|
215
197
|
assert !new.first?
|
|
216
198
|
assert new.last?
|
|
217
199
|
|
|
218
|
-
new =
|
|
219
|
-
assert_equal
|
|
200
|
+
new = DefaultScopedMixin.create
|
|
201
|
+
assert_equal 7, new.pos
|
|
220
202
|
assert !new.first?
|
|
221
203
|
assert new.last?
|
|
204
|
+
end
|
|
222
205
|
|
|
223
|
-
|
|
224
|
-
assert_equal 1,
|
|
225
|
-
|
|
226
|
-
|
|
206
|
+
def test_reordering
|
|
207
|
+
assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
|
|
208
|
+
|
|
209
|
+
DefaultScopedMixin.find(2).move_lower
|
|
210
|
+
assert_equal [1, 3, 2, 4], DefaultScopedMixin.find(:all).map(&:id)
|
|
211
|
+
|
|
212
|
+
DefaultScopedMixin.find(2).move_higher
|
|
213
|
+
assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
|
|
214
|
+
|
|
215
|
+
DefaultScopedMixin.find(1).move_to_bottom
|
|
216
|
+
assert_equal [2, 3, 4, 1], DefaultScopedMixin.find(:all).map(&:id)
|
|
217
|
+
|
|
218
|
+
DefaultScopedMixin.find(1).move_to_top
|
|
219
|
+
assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
|
|
220
|
+
|
|
221
|
+
DefaultScopedMixin.find(2).move_to_bottom
|
|
222
|
+
assert_equal [1, 3, 4, 2], DefaultScopedMixin.find(:all).map(&:id)
|
|
223
|
+
|
|
224
|
+
DefaultScopedMixin.find(4).move_to_top
|
|
225
|
+
assert_equal [4, 1, 3, 2], DefaultScopedMixin.find(:all).map(&:id)
|
|
227
226
|
end
|
|
228
227
|
|
|
229
228
|
def test_insert_at
|
|
230
|
-
new =
|
|
231
|
-
assert_equal
|
|
229
|
+
new = DefaultScopedMixin.create
|
|
230
|
+
assert_equal 5, new.pos
|
|
232
231
|
|
|
233
|
-
new =
|
|
234
|
-
assert_equal
|
|
232
|
+
new = DefaultScopedMixin.create
|
|
233
|
+
assert_equal 6, new.pos
|
|
235
234
|
|
|
236
|
-
new =
|
|
237
|
-
assert_equal
|
|
235
|
+
new = DefaultScopedMixin.create
|
|
236
|
+
assert_equal 7, new.pos
|
|
238
237
|
|
|
239
|
-
new4 =
|
|
240
|
-
assert_equal
|
|
238
|
+
new4 = DefaultScopedMixin.create
|
|
239
|
+
assert_equal 8, new4.pos
|
|
241
240
|
|
|
242
|
-
new4.insert_at(
|
|
243
|
-
assert_equal
|
|
241
|
+
new4.insert_at(2)
|
|
242
|
+
assert_equal 2, new4.pos
|
|
244
243
|
|
|
245
244
|
new.reload
|
|
246
|
-
assert_equal
|
|
245
|
+
assert_equal 8, new.pos
|
|
247
246
|
|
|
248
247
|
new.insert_at(2)
|
|
249
248
|
assert_equal 2, new.pos
|
|
250
249
|
|
|
251
250
|
new4.reload
|
|
252
|
-
assert_equal
|
|
251
|
+
assert_equal 3, new4.pos
|
|
253
252
|
|
|
254
|
-
new5 =
|
|
255
|
-
assert_equal
|
|
253
|
+
new5 = DefaultScopedMixin.create
|
|
254
|
+
assert_equal 9, new5.pos
|
|
256
255
|
|
|
257
256
|
new5.insert_at(1)
|
|
258
257
|
assert_equal 1, new5.pos
|
|
259
258
|
|
|
260
259
|
new4.reload
|
|
261
|
-
assert_equal
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def test_delete_middle
|
|
265
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
266
|
-
|
|
267
|
-
ListMixin.find(2).destroy
|
|
268
|
-
|
|
269
|
-
assert_equal [1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
270
|
-
|
|
271
|
-
assert_equal 1, ListMixin.find(1).pos
|
|
272
|
-
assert_equal 2, ListMixin.find(3).pos
|
|
273
|
-
assert_equal 3, ListMixin.find(4).pos
|
|
274
|
-
|
|
275
|
-
ListMixin.find(1).destroy
|
|
276
|
-
|
|
277
|
-
assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
278
|
-
|
|
279
|
-
assert_equal 1, ListMixin.find(3).pos
|
|
280
|
-
assert_equal 2, ListMixin.find(4).pos
|
|
281
|
-
end
|
|
282
|
-
|
|
283
|
-
def test_with_string_based_scope
|
|
284
|
-
new = ListWithStringScopeMixin.create(:parent_id => 500)
|
|
285
|
-
assert_equal 1, new.pos
|
|
286
|
-
assert new.first?
|
|
287
|
-
assert new.last?
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def test_nil_scope
|
|
291
|
-
new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create
|
|
292
|
-
new2.move_higher
|
|
293
|
-
assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
def test_remove_from_list_should_then_fail_in_list?
|
|
297
|
-
assert_equal true, ListMixin.find(1).in_list?
|
|
298
|
-
ListMixin.find(1).remove_from_list
|
|
299
|
-
assert_equal false, ListMixin.find(1).in_list?
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
def test_remove_from_list_should_set_position_to_nil
|
|
303
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
304
|
-
|
|
305
|
-
ListMixin.find(2).remove_from_list
|
|
306
|
-
|
|
307
|
-
assert_equal [2, 1, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
308
|
-
|
|
309
|
-
assert_equal 1, ListMixin.find(1).pos
|
|
310
|
-
assert_equal nil, ListMixin.find(2).pos
|
|
311
|
-
assert_equal 2, ListMixin.find(3).pos
|
|
312
|
-
assert_equal 3, ListMixin.find(4).pos
|
|
260
|
+
assert_equal 4, new4.pos
|
|
313
261
|
end
|
|
314
262
|
|
|
315
|
-
def
|
|
316
|
-
assert_equal [1, 2, 3, 4],
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
assert_equal 2,
|
|
325
|
-
assert_equal 3, ListMixin.find(4).pos
|
|
263
|
+
def test_update_position
|
|
264
|
+
assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
|
|
265
|
+
DefaultScopedMixin.find(2).set_list_position(4)
|
|
266
|
+
assert_equal [1, 3, 4, 2], DefaultScopedMixin.find(:all).map(&:id)
|
|
267
|
+
DefaultScopedMixin.find(2).set_list_position(2)
|
|
268
|
+
assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
|
|
269
|
+
DefaultScopedMixin.find(1).set_list_position(4)
|
|
270
|
+
assert_equal [2, 3, 4, 1], DefaultScopedMixin.find(:all).map(&:id)
|
|
271
|
+
DefaultScopedMixin.find(1).set_list_position(1)
|
|
272
|
+
assert_equal [1, 2, 3, 4], DefaultScopedMixin.find(:all).map(&:id)
|
|
326
273
|
end
|
|
327
274
|
|
|
328
|
-
|
|
329
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
330
|
-
|
|
331
|
-
# We need to trigger all the before_destroy callbacks without actually
|
|
332
|
-
# destroying the record so we can see the affect the callbacks have on
|
|
333
|
-
# the record.
|
|
334
|
-
# NOTE: Hotfix for rails3 ActiveRecord
|
|
335
|
-
list = ListMixin.find(2)
|
|
336
|
-
if list.respond_to?(:run_callbacks)
|
|
337
|
-
# Refactored to work according to Rails3 ActiveRSupport Callbacks <http://api.rubyonrails.org/classes/ActiveSupport/Callbacks.html>
|
|
338
|
-
list.run_callbacks :destroy, :before if rails_3
|
|
339
|
-
list.run_callbacks(:before_destroy) if !rails_3
|
|
340
|
-
else
|
|
341
|
-
list.send(:callback, :before_destroy)
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
275
|
+
end
|
|
345
276
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
277
|
+
class DefaultScopedWhereTest < ActsAsListTestCase
|
|
278
|
+
def setup
|
|
279
|
+
setup_db
|
|
280
|
+
(1..4).each { |counter| DefaultScopedWhereMixin.create! :pos => counter, :active => false }
|
|
350
281
|
end
|
|
351
282
|
|
|
352
|
-
def
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
new = ListMixin.create(:parent_id => 5)
|
|
283
|
+
def test_insert
|
|
284
|
+
new = DefaultScopedWhereMixin.create
|
|
356
285
|
assert_equal 5, new.pos
|
|
357
286
|
assert !new.first?
|
|
358
287
|
assert new.last?
|
|
359
288
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
def test_before_create_callback_adds_to_given_position
|
|
364
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
365
|
-
|
|
366
|
-
new = ListMixin.create(:pos => 1, :parent_id => 5)
|
|
367
|
-
assert_equal 1, new.pos
|
|
368
|
-
assert new.first?
|
|
369
|
-
assert !new.last?
|
|
370
|
-
|
|
371
|
-
assert_equal [5, 1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
372
|
-
|
|
373
|
-
new = ListMixin.create(:pos => 3, :parent_id => 5)
|
|
374
|
-
assert_equal 3, new.pos
|
|
289
|
+
new = DefaultScopedWhereMixin.create
|
|
290
|
+
assert_equal 6, new.pos
|
|
375
291
|
assert !new.first?
|
|
376
|
-
assert
|
|
377
|
-
|
|
378
|
-
assert_equal [5, 1, 6, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos').map(&:id)
|
|
379
|
-
end
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
class ListSubTest < Test::Unit::TestCase
|
|
383
|
-
|
|
384
|
-
def setup
|
|
385
|
-
setup_db
|
|
386
|
-
(1..4).each { |i| ((i % 2 == 1) ? ListMixinSub1 : ListMixinSub2).create! :pos => i, :parent_id => 5000 }
|
|
387
|
-
end
|
|
292
|
+
assert new.last?
|
|
388
293
|
|
|
389
|
-
|
|
390
|
-
|
|
294
|
+
new = DefaultScopedWhereMixin.create
|
|
295
|
+
assert_equal 7, new.pos
|
|
296
|
+
assert !new.first?
|
|
297
|
+
assert new.last?
|
|
391
298
|
end
|
|
392
299
|
|
|
393
300
|
def test_reordering
|
|
394
|
-
assert_equal [1, 2, 3, 4],
|
|
301
|
+
assert_equal [1, 2, 3, 4], DefaultScopedWhereMixin.where(:active => false).map(&:id)
|
|
395
302
|
|
|
396
|
-
|
|
397
|
-
assert_equal [1, 3, 2, 4],
|
|
303
|
+
DefaultScopedWhereMixin.where(:active => false).find(2).move_lower
|
|
304
|
+
assert_equal [1, 3, 2, 4], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
398
305
|
|
|
399
|
-
|
|
400
|
-
assert_equal [1, 2, 3, 4],
|
|
306
|
+
DefaultScopedWhereMixin.where(:active => false).find(2).move_higher
|
|
307
|
+
assert_equal [1, 2, 3, 4], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
401
308
|
|
|
402
|
-
|
|
403
|
-
assert_equal [2, 3, 4, 1],
|
|
309
|
+
DefaultScopedWhereMixin.where(:active => false).find(1).move_to_bottom
|
|
310
|
+
assert_equal [2, 3, 4, 1], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
404
311
|
|
|
405
|
-
|
|
406
|
-
assert_equal [1, 2, 3, 4],
|
|
312
|
+
DefaultScopedWhereMixin.where(:active => false).find(1).move_to_top
|
|
313
|
+
assert_equal [1, 2, 3, 4], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
407
314
|
|
|
408
|
-
|
|
409
|
-
assert_equal [1, 3, 4, 2],
|
|
315
|
+
DefaultScopedWhereMixin.where(:active => false).find(2).move_to_bottom
|
|
316
|
+
assert_equal [1, 3, 4, 2], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
410
317
|
|
|
411
|
-
|
|
412
|
-
assert_equal [4, 1, 3, 2],
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
def test_move_to_bottom_with_next_to_last_item
|
|
416
|
-
assert_equal [1, 2, 3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
|
417
|
-
ListMixin.find(3).move_to_bottom
|
|
418
|
-
assert_equal [1, 2, 4, 3], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
def test_next_prev
|
|
422
|
-
assert_equal ListMixin.find(2), ListMixin.find(1).lower_item
|
|
423
|
-
assert_nil ListMixin.find(1).higher_item
|
|
424
|
-
assert_equal ListMixin.find(3), ListMixin.find(4).higher_item
|
|
425
|
-
assert_nil ListMixin.find(4).lower_item
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
def test_injection
|
|
429
|
-
item = ListMixin.new("parent_id"=>1)
|
|
430
|
-
assert_equal '"mixins"."parent_id" = 1', item.scope_condition
|
|
431
|
-
assert_equal "pos", item.position_column
|
|
318
|
+
DefaultScopedWhereMixin.where(:active => false).find(4).move_to_top
|
|
319
|
+
assert_equal [4, 1, 3, 2], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
432
320
|
end
|
|
433
321
|
|
|
434
322
|
def test_insert_at
|
|
435
|
-
new =
|
|
436
|
-
assert_equal
|
|
323
|
+
new = DefaultScopedWhereMixin.create
|
|
324
|
+
assert_equal 5, new.pos
|
|
437
325
|
|
|
438
|
-
new =
|
|
439
|
-
assert_equal
|
|
326
|
+
new = DefaultScopedWhereMixin.create
|
|
327
|
+
assert_equal 6, new.pos
|
|
440
328
|
|
|
441
|
-
new =
|
|
442
|
-
assert_equal
|
|
329
|
+
new = DefaultScopedWhereMixin.create
|
|
330
|
+
assert_equal 7, new.pos
|
|
443
331
|
|
|
444
|
-
new4 =
|
|
445
|
-
assert_equal
|
|
332
|
+
new4 = DefaultScopedWhereMixin.create
|
|
333
|
+
assert_equal 8, new4.pos
|
|
446
334
|
|
|
447
|
-
new4.insert_at(
|
|
448
|
-
assert_equal
|
|
335
|
+
new4.insert_at(2)
|
|
336
|
+
assert_equal 2, new4.pos
|
|
449
337
|
|
|
450
338
|
new.reload
|
|
451
|
-
assert_equal
|
|
339
|
+
assert_equal 8, new.pos
|
|
452
340
|
|
|
453
341
|
new.insert_at(2)
|
|
454
342
|
assert_equal 2, new.pos
|
|
455
343
|
|
|
456
344
|
new4.reload
|
|
457
|
-
assert_equal
|
|
345
|
+
assert_equal 3, new4.pos
|
|
458
346
|
|
|
459
|
-
new5 =
|
|
460
|
-
assert_equal
|
|
347
|
+
new5 = DefaultScopedWhereMixin.create
|
|
348
|
+
assert_equal 9, new5.pos
|
|
461
349
|
|
|
462
350
|
new5.insert_at(1)
|
|
463
351
|
assert_equal 1, new5.pos
|
|
464
352
|
|
|
465
353
|
new4.reload
|
|
466
|
-
assert_equal
|
|
354
|
+
assert_equal 4, new4.pos
|
|
467
355
|
end
|
|
468
356
|
|
|
469
|
-
def
|
|
470
|
-
assert_equal [1, 2, 3, 4],
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
assert_equal [1, 3, 4],
|
|
475
|
-
|
|
476
|
-
assert_equal 1,
|
|
477
|
-
|
|
478
|
-
assert_equal 3,
|
|
479
|
-
|
|
480
|
-
ListMixin.find(1).destroy
|
|
481
|
-
|
|
482
|
-
assert_equal [3, 4], ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos').map(&:id)
|
|
483
|
-
|
|
484
|
-
assert_equal 1, ListMixin.find(3).pos
|
|
485
|
-
assert_equal 2, ListMixin.find(4).pos
|
|
357
|
+
def test_update_position
|
|
358
|
+
assert_equal [1, 2, 3, 4], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
359
|
+
DefaultScopedWhereMixin.where(:active => false).find(2).set_list_position(4)
|
|
360
|
+
assert_equal [1, 3, 4, 2], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
361
|
+
DefaultScopedWhereMixin.where(:active => false).find(2).set_list_position(2)
|
|
362
|
+
assert_equal [1, 2, 3, 4], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
363
|
+
DefaultScopedWhereMixin.where(:active => false).find(1).set_list_position(4)
|
|
364
|
+
assert_equal [2, 3, 4, 1], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
365
|
+
DefaultScopedWhereMixin.where(:active => false).find(1).set_list_position(1)
|
|
366
|
+
assert_equal [1, 2, 3, 4], DefaultScopedWhereMixin.where(:active => false).find(:all).map(&:id)
|
|
486
367
|
end
|
|
487
368
|
|
|
488
369
|
end
|
|
489
370
|
|
|
490
|
-
class
|
|
371
|
+
class MultiDestroyTest < ActsAsListTestCase
|
|
491
372
|
|
|
492
373
|
def setup
|
|
493
374
|
setup_db
|
|
494
|
-
(1..4).each { |counter| ArrayScopeListMixin.create! :pos => counter, :parent_id => 5, :parent_type => 'ParentClass' }
|
|
495
|
-
end
|
|
496
|
-
|
|
497
|
-
def teardown
|
|
498
|
-
teardown_db
|
|
499
375
|
end
|
|
500
376
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
377
|
+
# example:
|
|
378
|
+
#
|
|
379
|
+
# class TodoList < ActiveRecord::Base
|
|
380
|
+
# has_many :todo_items, :order => "position"
|
|
381
|
+
# accepts_nested_attributes_for :todo_items, :allow_destroy => true
|
|
382
|
+
# end
|
|
383
|
+
#
|
|
384
|
+
# class TodoItem < ActiveRecord::Base
|
|
385
|
+
# belongs_to :todo_list
|
|
386
|
+
# acts_as_list :scope => :todo_list
|
|
387
|
+
# end
|
|
388
|
+
#
|
|
389
|
+
# Assume that there are three items.
|
|
390
|
+
# The user mark two items as deleted, click save button, form will be post:
|
|
391
|
+
#
|
|
392
|
+
# todo_list.todo_items_attributes = [
|
|
393
|
+
# {id: 1, _destroy: true},
|
|
394
|
+
# {id: 2, _destroy: true}
|
|
395
|
+
# ]
|
|
396
|
+
#
|
|
397
|
+
# Save toto_list, the position of item #3 should eql 1.
|
|
398
|
+
#
|
|
399
|
+
def test_destroy
|
|
400
|
+
new1 = DefaultScopedMixin.create
|
|
401
|
+
assert_equal 1, new1.pos
|
|
402
|
+
|
|
403
|
+
new2 = DefaultScopedMixin.create
|
|
404
|
+
assert_equal 2, new2.pos
|
|
405
|
+
|
|
406
|
+
new3 = DefaultScopedMixin.create
|
|
407
|
+
assert_equal 3, new3.pos
|
|
408
|
+
|
|
409
|
+
new1.destroy
|
|
410
|
+
new2.destroy
|
|
411
|
+
new3.reload
|
|
412
|
+
assert_equal 1, new3.pos
|
|
521
413
|
end
|
|
414
|
+
end
|
|
522
415
|
|
|
523
|
-
|
|
524
|
-
assert_equal [1, 2, 3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
|
|
525
|
-
ArrayScopeListMixin.find(3).move_to_bottom
|
|
526
|
-
assert_equal [1, 2, 4, 3], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
|
|
527
|
-
end
|
|
416
|
+
#class TopAdditionMixin < Mixin
|
|
528
417
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
assert_nil ArrayScopeListMixin.find(1).higher_item
|
|
532
|
-
assert_equal ArrayScopeListMixin.find(3), ArrayScopeListMixin.find(4).higher_item
|
|
533
|
-
assert_nil ArrayScopeListMixin.find(4).lower_item
|
|
534
|
-
end
|
|
418
|
+
class TopAdditionTest < ActsAsListTestCase
|
|
419
|
+
include Shared::TopAddition
|
|
535
420
|
|
|
536
|
-
def
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
assert_equal "pos", item.position_column
|
|
421
|
+
def setup
|
|
422
|
+
setup_db
|
|
423
|
+
super
|
|
540
424
|
end
|
|
425
|
+
end
|
|
541
426
|
|
|
542
|
-
def test_insert
|
|
543
|
-
new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
|
|
544
|
-
assert_equal 1, new.pos
|
|
545
|
-
assert new.first?
|
|
546
|
-
assert new.last?
|
|
547
|
-
|
|
548
|
-
new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
|
|
549
|
-
assert_equal 2, new.pos
|
|
550
|
-
assert !new.first?
|
|
551
|
-
assert new.last?
|
|
552
427
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
assert !new.first?
|
|
556
|
-
assert new.last?
|
|
428
|
+
class TopAdditionTestWithDefault < ActsAsListTestCase
|
|
429
|
+
include Shared::TopAddition
|
|
557
430
|
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
assert new.last?
|
|
431
|
+
def setup
|
|
432
|
+
setup_db_with_default
|
|
433
|
+
super
|
|
562
434
|
end
|
|
435
|
+
end
|
|
563
436
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
|
|
569
|
-
assert_equal 2, new.pos
|
|
570
|
-
|
|
571
|
-
new = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
|
|
572
|
-
assert_equal 3, new.pos
|
|
573
|
-
|
|
574
|
-
new4 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
|
|
575
|
-
assert_equal 4, new4.pos
|
|
576
|
-
|
|
577
|
-
new4.insert_at(3)
|
|
578
|
-
assert_equal 3, new4.pos
|
|
579
|
-
|
|
580
|
-
new.reload
|
|
581
|
-
assert_equal 4, new.pos
|
|
582
|
-
|
|
583
|
-
new.insert_at(2)
|
|
584
|
-
assert_equal 2, new.pos
|
|
585
|
-
|
|
586
|
-
new4.reload
|
|
587
|
-
assert_equal 4, new4.pos
|
|
588
|
-
|
|
589
|
-
new5 = ArrayScopeListMixin.create(:parent_id => 20, :parent_type => 'ParentClass')
|
|
590
|
-
assert_equal 5, new5.pos
|
|
591
|
-
|
|
592
|
-
new5.insert_at(1)
|
|
593
|
-
assert_equal 1, new5.pos
|
|
594
|
-
|
|
595
|
-
new4.reload
|
|
596
|
-
assert_equal 5, new4.pos
|
|
437
|
+
class RespectMixinProtection < ActsAsListTestCase
|
|
438
|
+
def setup
|
|
439
|
+
setup_db_with_default
|
|
440
|
+
super
|
|
597
441
|
end
|
|
598
442
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
assert_equal
|
|
605
|
-
|
|
606
|
-
assert_equal 1, ArrayScopeListMixin.find(1).pos
|
|
607
|
-
assert_equal 2, ArrayScopeListMixin.find(3).pos
|
|
608
|
-
assert_equal 3, ArrayScopeListMixin.find(4).pos
|
|
609
|
-
|
|
610
|
-
ArrayScopeListMixin.find(1).destroy
|
|
611
|
-
|
|
612
|
-
assert_equal [3, 4], ArrayScopeListMixin.find(:all, :conditions => "parent_id = 5 AND parent_type = 'ParentClass'", :order => 'pos').map(&:id)
|
|
613
|
-
|
|
614
|
-
assert_equal 1, ArrayScopeListMixin.find(3).pos
|
|
615
|
-
assert_equal 2, ArrayScopeListMixin.find(4).pos
|
|
443
|
+
# if an attribute is set attr_protected
|
|
444
|
+
# it should be unchanged by update_attributes
|
|
445
|
+
def test_unmodified_protection
|
|
446
|
+
a = ProtectedMixin.new
|
|
447
|
+
a.update_attributes({:active => false})
|
|
448
|
+
assert_equal true, a.active
|
|
616
449
|
end
|
|
617
450
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
451
|
+
# even after the acts_as_list mixin is joined
|
|
452
|
+
# that protection should continue to exist
|
|
453
|
+
def test_still_protected
|
|
454
|
+
b = ProtectedListMixin.new
|
|
455
|
+
b.update_attributes({:active => false})
|
|
456
|
+
assert_equal true, b.active
|
|
622
457
|
end
|
|
623
458
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
assert_equal
|
|
630
|
-
|
|
631
|
-
assert_equal 1, ArrayScopeListMixin.find(1).pos
|
|
632
|
-
assert_equal nil, ArrayScopeListMixin.find(2).pos
|
|
633
|
-
assert_equal 2, ArrayScopeListMixin.find(3).pos
|
|
634
|
-
assert_equal 3, ArrayScopeListMixin.find(4).pos
|
|
459
|
+
# similarly, if a class lacks mass_assignment protection
|
|
460
|
+
# it should be able to be changed
|
|
461
|
+
def test_unprotected
|
|
462
|
+
a = UnProtectedMixin.new
|
|
463
|
+
a.update_attributes({:active => false})
|
|
464
|
+
assert_equal false, a.active
|
|
635
465
|
end
|
|
636
466
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
assert_equal
|
|
644
|
-
|
|
645
|
-
assert_equal 1, ArrayScopeListMixin.find(1).pos
|
|
646
|
-
assert_equal 2, ArrayScopeListMixin.find(3).pos
|
|
647
|
-
assert_equal 3, ArrayScopeListMixin.find(4).pos
|
|
467
|
+
# and it should continue to be mutable by mass_assignment
|
|
468
|
+
# even after the acts_as_list plugin has been joined
|
|
469
|
+
def test_still_unprotected_mixin
|
|
470
|
+
b = UnProtectedListMixin.new
|
|
471
|
+
b.assign_attributes({:active => false})
|
|
472
|
+
# p UnProtectedListMixin.accessible_attributes.length
|
|
473
|
+
assert_equal false, b.active
|
|
648
474
|
end
|
|
649
475
|
|
|
650
476
|
end
|