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.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +74 -0
- data/Rakefile +46 -0
- data/install.rb +4 -0
- data/lib/has_many_booleans.rb +335 -0
- data/lib/has_many_booleans/simple_bitset.rb +64 -0
- data/rails/init.rb +1 -0
- data/test/database.yml +6 -0
- data/test/debug.log +710 -0
- data/test/has_many_booleans_plugin.sqlite3 +0 -0
- data/test/has_many_booleans_test.rb +396 -0
- data/test/schema.rb +36 -0
- data/test/simple_bitset_test.rb +22 -0
- data/test/test_helper.rb +43 -0
- data/uninstall.rb +1 -0
- metadata +75 -0
Binary file
|
@@ -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
|
+
|