has_many_booleans 0.9

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.
@@ -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
+