has_many_booleans 0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,396 @@
1
+ # has_many_booleans (c) 2010 Jan Lelis, released under the MIT license
2
+ # available at <http://github.com/janlelis/has_many_booleans>
3
+ # more info at <http://rbjl.net/22>
4
+
5
+ require File.dirname(__FILE__) + '/test_helper.rb'
6
+
7
+ class HasManyBooleansTest < ActiveSupport::TestCase
8
+ load_schema
9
+
10
+ # # #
11
+ # create all kinds of model classes
12
+ #
13
+ class Default < ActiveRecord::Base
14
+ has_many_booleans :name, :password, :admin,
15
+ :true => [:name, :password],
16
+ :append => 'bla'
17
+ end
18
+
19
+ class ManyOption < ActiveRecord::Base
20
+ has_many_booleans :a, :b, :admin, :name, :password,
21
+ :true => [ :b],
22
+ :suffixes => %w| 1 2 3 1 2 ? ! = . k l |,
23
+ :append => '145',
24
+ :self => true,
25
+ :lazy => false
26
+ end
27
+
28
+ class NoOption < ActiveRecord::Base
29
+ has_many_booleans :name, :password, :admin
30
+ end
31
+
32
+ class Hmb < ActiveRecord::Base
33
+ hmb :name, :password, :admin, :append => 'blubb'
34
+ end
35
+
36
+ class BooleansAsHash < ActiveRecord::Base
37
+ has_many_booleans({ :name => 22,
38
+ :password => 5,
39
+ :admin => 7 },
40
+ :append => 'bla')
41
+ end
42
+
43
+ class Append < ActiveRecord::Base
44
+ has_many_booleans :name, :password, :admin, :append => 'bla'
45
+ end
46
+
47
+ class AppendNil < ActiveRecord::Base
48
+ has_many_booleans :name, :password, :admin, :append => nil
49
+ end
50
+
51
+ class Field < ActiveRecord::Base
52
+ has_many_booleans :name, :password, :admin, :field => 'bools'
53
+ end
54
+
55
+ class SuffixNone < ActiveRecord::Base
56
+ has_many_booleans :name, :password, :admin, :suffixes => nil
57
+ end
58
+
59
+ class SuffixEqualOnly < ActiveRecord::Base
60
+ has_many_booleans :name, :password, :admin, :suffixes => ['=']
61
+ end
62
+
63
+ class SuffixQuestionOnly < ActiveRecord::Base
64
+ has_many_booleans :name, :password, :admin, :suffixes => ['?']
65
+ end
66
+
67
+ class SuffixExclamationOnly < ActiveRecord::Base
68
+ has_many_booleans :name, :password, :admin, :suffixes => ['!']
69
+ end
70
+
71
+ class Self < ActiveRecord::Base
72
+ has_many_booleans :name, :password, :admin, :self => true
73
+ end
74
+
75
+ class SelfAppendNil < ActiveRecord::Base
76
+ has_many_booleans :name, :password, :admin, :self => true, :append => nil
77
+ end
78
+
79
+ class SelfName < ActiveRecord::Base
80
+ has_many_booleans :name, :password, :admin, :self => 'active_', :self_value => true
81
+ end
82
+
83
+ class ValidateTest < ActiveRecord::Base
84
+ has_many_booleans :name, :password, :admin
85
+
86
+ validates_true :name
87
+ validates_false :password
88
+ end
89
+
90
+ class ArCallback < ActiveRecord::Base
91
+ has_many_booleans :name, :password, :admin
92
+
93
+ def after_initialize
94
+ self.name = "Yukihiro"
95
+ end
96
+
97
+ def before_save
98
+ self.name = 'matz'
99
+ end
100
+ end
101
+
102
+ class LazyFalse < ActiveRecord::Base
103
+ has_many_booleans :name, :password, :admin, :lazy => false
104
+ end
105
+
106
+ class FalseValue < ActiveRecord::Base
107
+ has_many_booleans :name, :password, :admin, :false_values => ["super", 'toll', 3]
108
+ end
109
+
110
+ class Scope < ActiveRecord::Base
111
+ has_many_booleans :name, :password, :admin, :self => true
112
+ end
113
+
114
+ # # #
115
+ # instances helpers
116
+ #
117
+ def create_instances
118
+ @instances = {
119
+ :default => Default.new,
120
+ :many_option => ManyOption.new,
121
+ :no_option => NoOption.new,
122
+ :booleans_as_hash => BooleansAsHash.new,
123
+ :hmb => Hmb.new,
124
+ :append => Append.new,
125
+ :append_nil => AppendNil.new,
126
+ :field => Field.new,
127
+ :suffix_none => SuffixNone.new,
128
+ :suffix_question_only => SuffixQuestionOnly.new,
129
+ :suffix_equal_only => SuffixEqualOnly.new,
130
+ :suffix_exclamation_only => SuffixExclamationOnly.new,
131
+ :self => Self.new,
132
+ :self_name => SelfName.new,
133
+ :ar_callback => ArCallback.new,
134
+ :lazy_false => LazyFalse.new,
135
+ :false_value => FalseValue.new,
136
+ }
137
+ @booleans_options = Hash[ @instances.map{|k,v| [k, v.class.booleans_options]} ]
138
+ end
139
+
140
+ def create_instance(which, *params)
141
+ @a = which.new *params
142
+ @o = which.booleans_options
143
+ end
144
+
145
+ def loop_instances(with_assign = false)
146
+ cur_actions = @instances.each
147
+ cur_booleans_options = @booleans_options.each
148
+
149
+ loop{
150
+ @n, @a = cur_actions.next # name, instances
151
+ @o = cur_booleans_options.next[1] # booleans_options
152
+ next if with_assign &&( !@o[:suffixes].include?('=') || !@o[:append] || @o[:append].empty?) # or name does not work (existing method overwrite protection)
153
+ yield
154
+ }
155
+ end
156
+
157
+ # helper for often called methods
158
+ def snd(attr_name, suffix = '', value = nil)
159
+ if suffix == '='
160
+ @a.send( "#{attr_name}#{@o[:append] || ''}#{suffix}", value)
161
+ else
162
+ @a.send "#{attr_name}#{@o[:append] || ''}#{suffix}"
163
+ end
164
+ # rescue => e
165
+ # p "#{e} -- #{@a} -- #{@o}"
166
+ end
167
+
168
+ # # #
169
+ # weak test of setup
170
+ #
171
+ test 'create_instances' do
172
+ assert_nothing_raised{
173
+ assert_kind_of @a.class, @a
174
+ }
175
+ end
176
+
177
+ # # #
178
+ # class methods
179
+ #
180
+ test 'booleans_options get parsed the right way' do
181
+ create_instance ManyOption
182
+ assert_equal @o[:append], '_145'
183
+ assert_equal @o[:true], [:b]
184
+ assert_equal (@o[:suffixes]||[]).sort, %w| ! = ? |
185
+ end
186
+
187
+ # # #
188
+ # general behaivour
189
+ #
190
+ test 'methods exist' do
191
+ create_instances and loop_instances do
192
+ assert_nothing_raised { snd :name }
193
+ assert_raise( NoMethodError ) { snd :dont_know_this_attr }
194
+ assert_raise( NoMethodError ) { @a.send :name_ru903gfjh209gh3209p23 }
195
+ end
196
+ end
197
+
198
+ test 'different instances' do
199
+ create_instance NoOption
200
+ a = @a
201
+ snd :name, '=', true
202
+ create_instance NoOption
203
+ assert a.name_activated
204
+ assert_not snd :name
205
+
206
+ create_instance SelfName
207
+ a = @a
208
+ a.active_ = false
209
+ create_instance SelfName
210
+ assert @a.active_
211
+ assert_not a.active_
212
+ end
213
+
214
+ test 'set and unset (with =)' do
215
+ create_instances and loop_instances(true) do
216
+ ( snd :name, '=', false )#, "#{@a.class},#{p :O;snd :name, '=', false}"
217
+ assert_not snd :name
218
+ snd :name, '=', true
219
+ assert snd :name
220
+
221
+ snd :password, '=', false
222
+ assert_not snd :password
223
+ snd :password, '=', true
224
+ assert snd :password
225
+ end
226
+ end
227
+
228
+ test 'save and load (with =)' do
229
+ create_instances and loop_instances(true) do
230
+ [:name, :password].each{ |what|
231
+ snd what, '=', false
232
+ assert @a.save
233
+ tmp = @a.class
234
+
235
+ assert_instance_of @a = @a.class.last, tmp
236
+ assert_not snd what
237
+
238
+ snd what, '=', true
239
+ assert @a.save
240
+ tmp = @a.class
241
+
242
+ assert_instance_of @a = @a.class.last, tmp
243
+ assert snd what
244
+ }
245
+ end
246
+ end
247
+
248
+ test 'right default values' do
249
+ create_instance Default
250
+ assert snd :name
251
+ assert snd :password
252
+ assert_not snd :admin
253
+ end
254
+
255
+ test "dont overwrite existing attrs" do
256
+ create_instance AppendNil
257
+ @a.name = 'Yukihiro'
258
+ assert @a.save
259
+ @a = AppendNil.last
260
+ assert_equal @a.name, 'Yukihiro'
261
+ end
262
+
263
+ test 'ar callbacks work' do
264
+ create_instance ArCallback
265
+ assert_equal @a.name, 'Yukihiro'
266
+ assert @a.valid?
267
+ @a.save
268
+ assert_equal @a.name, 'matz'
269
+ end
270
+
271
+ # # #
272
+ # booleans_options
273
+ #
274
+ test 'suffixes' do
275
+ create_instance SuffixNone
276
+ assert_nothing_raised { snd :name }
277
+ assert_raise( NoMethodError ) { snd :name, '?' }
278
+ assert_raise( NoMethodError ) { snd :name, '!' }
279
+ assert_raise( NoMethodError ) { snd :name, '=' }
280
+ assert_raise( NoMethodError ) { snd :name, '=', 9999 }
281
+
282
+ create_instance SuffixQuestionOnly
283
+ assert_nothing_raised { snd :name }
284
+ assert_nothing_raised { snd :name, '?' }
285
+ assert_raise( NoMethodError ) { snd :name, '!' }
286
+ assert_raise( NoMethodError ) { snd :name, '=' }
287
+ assert_raise( NoMethodError ) { snd :name, '=', 9999 }
288
+
289
+ create_instance SuffixExclamationOnly
290
+ assert_nothing_raised { snd :name }
291
+ assert_raise( NoMethodError ) { snd :name, '?' }
292
+ assert_nothing_raised { snd :name, '!' }
293
+ assert_raise( NoMethodError ) { snd :name, '=' }
294
+ assert_raise( NoMethodError ) { snd :name, '=', 9999 }
295
+
296
+ create_instance SuffixEqualOnly
297
+ assert_nothing_raised { snd :name }
298
+ assert_raise( NoMethodError ) { snd :name, '?' }
299
+ assert_raise( NoMethodError ) { snd :name, '!' }
300
+ assert_nothing_raised { snd :name, '=' }
301
+ assert_nothing_raised { snd :name, '=', 9999 }
302
+ end
303
+
304
+ test 'self' do
305
+ create_instance Default
306
+ assert_raise( NoMethodError ) { @a.send @o[:append] }
307
+
308
+ create_instance Self
309
+ assert_nothing_raised { @a.send @o[:append][1..-1] }
310
+ assert_equal @a.send( @o[:append][1..-1] ), false
311
+ @a.send( @o[:append][1..-1] + '=', 324 )
312
+ assert_equal @a.send( @o[:append][1..-1] ), true
313
+
314
+ assert_raise( RuntimeError ) {
315
+ create_instance SelfAppendNil
316
+ }
317
+
318
+ create_instance SelfName
319
+ assert_nothing_raised { @a.send @o[:self] }
320
+ assert_equal @a.send( @o[:self] ), true
321
+ end
322
+
323
+ test "lazyness (with assign)" do
324
+ create_instances and loop_instances(true) do
325
+ remember = @a.send( @o[:field] )
326
+ snd( :name, '=', !snd(:name) )
327
+ if @o[:lazy] # normal setting
328
+ assert_equal remember, @a.send( @o[:field] )
329
+ else
330
+ assert_not_equal remember, @a.send( @o[:field] )
331
+
332
+ end
333
+ end
334
+ end
335
+
336
+ test "false_values (with assign)" do
337
+ create_instance FalseValue
338
+
339
+ snd :name, '=', true
340
+ snd :name, '=', 'super'
341
+ assert_not snd :name
342
+ snd :name, '=', 3
343
+ assert_not snd :name
344
+ snd :name, '=', 99
345
+ assert snd :name
346
+ end
347
+
348
+ # scopes
349
+ test 'scopes' do
350
+ # create dummy data
351
+ create_instance Scope #1
352
+ @a.save
353
+ create_instance Scope #2
354
+ @a.activated!
355
+ @a.password_activated!
356
+ @a.save
357
+ create_instance Scope #3
358
+ @a.activated!
359
+ @a.save
360
+ create_instance Scope #4
361
+ @a.password_activated!
362
+ @a.save
363
+ create_instance Scope #5
364
+ @a.name_activated!
365
+ @a.save
366
+
367
+ # test queries
368
+ assert_equal Scope.true(:name), [Scope.find(5)]
369
+ assert_equal Scope.false, Scope.find(1, 4, 5)
370
+ assert_equal Scope.true(:name, :password), Scope.find(2, 4, 5)
371
+ assert_equal Scope.true(:name).true(:password), []
372
+ end
373
+
374
+ # validations
375
+ test 'validates_true' do
376
+ create_instance ValidateTest
377
+
378
+ snd :password, '=', false
379
+ snd :name, '=', false
380
+ assert_not @a.save, @a.errors.full_messages
381
+ snd :name, '=', true
382
+ assert @a.save, @a.errors.full_messages
383
+ end
384
+
385
+ test 'validates_false' do
386
+ create_instance ValidateTest
387
+
388
+ snd :name, '=', true
389
+ snd :password, '=', true
390
+ assert_not @a.save, @a.errors.full_messages
391
+ snd :password, '=', false
392
+ assert @a.save, @a.errors.full_messages
393
+ end
394
+
395
+ end
396
+
data/test/schema.rb ADDED
@@ -0,0 +1,36 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ %w|
3
+ appends
4
+ append_nils
5
+ defaults
6
+ many_options
7
+ no_options
8
+ hmbs
9
+ suffix_nones
10
+ suffix_question_onlies
11
+ suffix_equal_onlies
12
+ suffix_exclamation_onlies
13
+ selves
14
+ self_append_nils
15
+ self_names
16
+ ar_callbacks
17
+ lazy_falses
18
+ booleans_as_hashes
19
+ single_hashes
20
+ validate_tests
21
+ false_values
22
+ scopes
23
+ |.each do |table_name|
24
+ create_table table_name, :force => true do |t|
25
+ t.string :name
26
+ t.integer :booleans
27
+ end
28
+ end
29
+
30
+ create_table 'fields', :force => true do |t|
31
+ t.string :name
32
+ t.integer :bools
33
+ end
34
+
35
+ end
36
+
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class SimpleBitsetTest < ActiveSupport::TestCase
4
+ test 'to_bra' do
5
+ assert_equal 0.to_bra, []
6
+ assert_equal 1.to_bra, [0]
7
+ assert_equal 2.to_bra, [1]
8
+ assert_equal 3.to_bra, [0,1]
9
+ assert_equal 4.to_bra, [2]
10
+ assert_equal 999999999999999999.to_bra, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 22, 24, 25, 26, 29, 31, 32, 33, 36, 37, 39, 41, 42, 44, 45, 47, 53, 54, 55, 56, 58, 59]
11
+ end
12
+
13
+ test 'to_bri' do
14
+ assert_equal 0, [].to_bri
15
+ assert_equal 1, [0].to_bri
16
+ assert_equal 2, [1].to_bri
17
+ assert_equal 3, [0,1].to_bri
18
+ assert_equal 4, [2].to_bri
19
+ assert_equal 999999999999999999, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 22, 24, 25, 26, 29, 31, 32, 33, 36, 37, 39, 41, 42, 44, 45, 47, 53, 54, 55, 56, 58, 59].to_bri
20
+ end
21
+ end
22
+