quality_extensions 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. data/Readme +54 -0
  2. data/lib/qualitysmith_extensions/all.rb +4 -0
  3. data/lib/qualitysmith_extensions/array/all.rb +2 -0
  4. data/lib/qualitysmith_extensions/array/average.rb +44 -0
  5. data/lib/qualitysmith_extensions/array/classify.rb +97 -0
  6. data/lib/qualitysmith_extensions/array/expand_ranges.rb +52 -0
  7. data/lib/qualitysmith_extensions/array/group_by.rb +134 -0
  8. data/lib/qualitysmith_extensions/array/sequence.rb +66 -0
  9. data/lib/qualitysmith_extensions/array/shell_escape.rb +36 -0
  10. data/lib/qualitysmith_extensions/array/to_a_recursive.rb +41 -0
  11. data/lib/qualitysmith_extensions/array/to_query_string.rb +96 -0
  12. data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
  13. data/lib/qualitysmith_extensions/colored/toggleability.rb +62 -0
  14. data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
  15. data/lib/qualitysmith_extensions/console/command.facets.1.8.54.rb +748 -0
  16. data/lib/qualitysmith_extensions/console/command.rb +944 -0
  17. data/lib/qualitysmith_extensions/date/all.rb +2 -0
  18. data/lib/qualitysmith_extensions/date/deprecated.rb +40 -0
  19. data/lib/qualitysmith_extensions/date/iso8601.rb +31 -0
  20. data/lib/qualitysmith_extensions/date/month_ranges.rb +122 -0
  21. data/lib/qualitysmith_extensions/dir/each_child.rb +58 -0
  22. data/lib/qualitysmith_extensions/enumerable/enum.rb +69 -0
  23. data/lib/qualitysmith_extensions/enumerable/select_until.rb +4 -0
  24. data/lib/qualitysmith_extensions/enumerable/select_while.rb +109 -0
  25. data/lib/qualitysmith_extensions/exception/inspect_with_backtrace.rb +65 -0
  26. data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +34 -0
  27. data/lib/qualitysmith_extensions/file_test/binary_file.rb +110 -0
  28. data/lib/qualitysmith_extensions/find/select.rb +68 -0
  29. data/lib/qualitysmith_extensions/global_variable_set.rb +153 -0
  30. data/lib/qualitysmith_extensions/hash/all.rb +2 -0
  31. data/lib/qualitysmith_extensions/hash/to_date.rb +34 -0
  32. data/lib/qualitysmith_extensions/hash/to_query_string.rb +121 -0
  33. data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
  34. data/lib/qualitysmith_extensions/kernel/autoreload.rb +128 -0
  35. data/lib/qualitysmith_extensions/kernel/backtrace.rb +71 -0
  36. data/lib/qualitysmith_extensions/kernel/capture_output.rb +115 -0
  37. data/lib/qualitysmith_extensions/kernel/die.rb +49 -0
  38. data/lib/qualitysmith_extensions/kernel/example_printer.rb +81 -0
  39. data/lib/qualitysmith_extensions/kernel/filter_output.rb +108 -0
  40. data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
  41. data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
  42. data/lib/qualitysmith_extensions/kernel/require_all.rb +186 -0
  43. data/lib/qualitysmith_extensions/kernel/require_local_all.rb +4 -0
  44. data/lib/qualitysmith_extensions/kernel/require_once.rb +18 -0
  45. data/lib/qualitysmith_extensions/kernel/simulate_input.rb +52 -0
  46. data/lib/qualitysmith_extensions/kernel/trap_chain.rb +61 -0
  47. data/lib/qualitysmith_extensions/kernel/windows_platform.rb +46 -0
  48. data/lib/qualitysmith_extensions/module/alias_method.rb +6 -0
  49. data/lib/qualitysmith_extensions/module/alias_method_chain.rb +165 -0
  50. data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
  51. data/lib/qualitysmith_extensions/module/attribute_accessors.rb +49 -0
  52. data/lib/qualitysmith_extensions/module/basename.rb +76 -0
  53. data/lib/qualitysmith_extensions/module/bool_attr_accessor.rb +497 -0
  54. data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
  55. data/lib/qualitysmith_extensions/module/create.rb +315 -0
  56. data/lib/qualitysmith_extensions/module/create_setter.rb +9 -0
  57. data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
  58. data/lib/qualitysmith_extensions/module/guard_method.rb +312 -0
  59. data/lib/qualitysmith_extensions/module/includable_once.rb +10 -0
  60. data/lib/qualitysmith_extensions/module/join.rb +66 -0
  61. data/lib/qualitysmith_extensions/module/malias_method_chain.rb +92 -0
  62. data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
  63. data/lib/qualitysmith_extensions/module/namespace.rb +112 -0
  64. data/lib/qualitysmith_extensions/module/parents.rb +61 -0
  65. data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
  66. data/lib/qualitysmith_extensions/module/split.rb +55 -0
  67. data/lib/qualitysmith_extensions/month.rb +66 -0
  68. data/lib/qualitysmith_extensions/mutex/if_available.rb +75 -0
  69. data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
  70. data/lib/qualitysmith_extensions/object/default.rb +69 -0
  71. data/lib/qualitysmith_extensions/object/if_else.rb +157 -0
  72. data/lib/qualitysmith_extensions/object/ignore_access.rb +84 -0
  73. data/lib/qualitysmith_extensions/object/mcall.rb +92 -0
  74. data/lib/qualitysmith_extensions/object/methods.rb +63 -0
  75. data/lib/qualitysmith_extensions/object/send_if.rb +151 -0
  76. data/lib/qualitysmith_extensions/object/send_if_not_nil.rb +35 -0
  77. data/lib/qualitysmith_extensions/object/singleton_send.rb +129 -0
  78. data/lib/qualitysmith_extensions/regexp/join.rb +111 -0
  79. data/lib/qualitysmith_extensions/string/all.rb +2 -0
  80. data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
  81. data/lib/qualitysmith_extensions/string/digits_only.rb +27 -0
  82. data/lib/qualitysmith_extensions/string/each_char_with_index.rb +41 -0
  83. data/lib/qualitysmith_extensions/string/md5.rb +29 -0
  84. data/lib/qualitysmith_extensions/string/shell_escape.rb +43 -0
  85. data/lib/qualitysmith_extensions/string/to_underscored_label.rb +37 -0
  86. data/lib/qualitysmith_extensions/string/with_knowledge_of_color.rb +64 -0
  87. data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
  88. data/lib/qualitysmith_extensions/symbol/match.rb +157 -0
  89. data/lib/qualitysmith_extensions/template.rb +33 -0
  90. data/lib/qualitysmith_extensions/test/all.rb +2 -0
  91. data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
  92. data/lib/qualitysmith_extensions/test/assert_changed.rb +66 -0
  93. data/lib/qualitysmith_extensions/test/assert_exception.rb +66 -0
  94. data/lib/qualitysmith_extensions/test/assert_includes.rb +36 -0
  95. data/lib/qualitysmith_extensions/test/assert_user_error.rb +37 -0
  96. data/lib/qualitysmith_extensions/test/difference_highlighting.rb +323 -0
  97. data/lib/qualitysmith_extensions/time/all.rb +2 -0
  98. data/lib/qualitysmith_extensions/time/deprecated.rb +31 -0
  99. data/test/all.rb +16 -0
  100. metadata +148 -0
@@ -0,0 +1,43 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes.
6
+ # Developer notes::
7
+ # * May not have taken every single case into consideration. Needs a bit more testing.
8
+ # * public/private/protected?
9
+ # * Tests for this method can be found in ../object/ancestry_of_method.rb . It made more sense to test those two methods together;
10
+ # yet it's still to _use_ module/ancestry_of_instance_method.rb without using ../object/ancestry_of_method.rb.
11
+ #++
12
+
13
+ class Module
14
+
15
+ # Returns the module/class which defined the given instance method. If more than one module/class defined the method, returns the _closest_
16
+ # ancestor to have defined it (would be +self+ if it is defined in +self+).
17
+ #
18
+ # This looks at the results of <tt>instance_methods</tt>, which means that if you call this on a module/class, it will _only_ look
19
+ # at _instance_ methods. Thus, (unlike +ancestry_of_method+) it _only_ makes sense to call this method on modules/classes,
20
+ # not _instances_ of those modules/classes.
21
+ #
22
+ # Example:
23
+ # class Base
24
+ # def it; end
25
+ # end
26
+ # class SubWithIt < Base
27
+ # def it; end
28
+ # end
29
+ # class SubWithoutIt < Base
30
+ # end
31
+ # SubWithIt.ancestors # => [SubWithIt, Base, Object, Kernel]
32
+ # SubWithIt.ancestry_of_instance_method(:it) # => SubWithIt # (Stops with self)
33
+ # SubWithoutIt.ancestry_of_instance_method(:it) # => Base # (Goes one step up the ancestry tree)
34
+ #
35
+ # Returns nil if it cannot be found in self or in any ancestor.
36
+ def ancestry_of_instance_method(method_name)
37
+ method_name = method_name.to_s
38
+ self.ancestors.find do |ancestor|
39
+ ancestor.instance_methods(false).include? method_name
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,49 @@
1
+ # Copied from ActiveSupport because I couldn't get the ones in Facets to work...
2
+
3
+ # Extends the module object with module and instance accessors for class attributes,
4
+ # just like the native attr* accessors for instance attributes.
5
+ class Module # :nodoc:
6
+ def mattr_reader(*syms)
7
+ syms.each do |sym|
8
+ class_eval(<<-EOS, __FILE__, __LINE__+1)
9
+ unless defined? @@#{sym}
10
+ @@#{sym} = nil
11
+ end
12
+
13
+ def self.#{sym}
14
+ @@#{sym}
15
+ end
16
+
17
+ def #{sym}
18
+ @@#{sym}
19
+ end
20
+ EOS
21
+ end
22
+ end
23
+ alias_method :cattr_reader, :mattr_reader
24
+
25
+ def mattr_writer(*syms)
26
+ syms.each do |sym|
27
+ class_eval(<<-EOS, __FILE__, __LINE__+1)
28
+ unless defined? @@#{sym}
29
+ @@#{sym} = nil
30
+ end
31
+
32
+ def self.#{sym}=(obj)
33
+ @@#{sym} = obj
34
+ end
35
+
36
+ def #{sym}=(obj)
37
+ @@#{sym} = obj
38
+ end
39
+ EOS
40
+ end
41
+ end
42
+ alias_method :cattr_writer, :mattr_writer
43
+
44
+ def mattr_accessor(*syms)
45
+ mattr_reader(*syms)
46
+ mattr_writer(*syms)
47
+ end
48
+ alias_method :cattr_accessor, :mattr_accessor
49
+ end
@@ -0,0 +1,76 @@
1
+ #--
2
+ # Author:: Tyler Rick
3
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes.
6
+ # Developer notes::
7
+ # Changes::
8
+ #++
9
+
10
+
11
+ require 'rubygems'
12
+ require 'facets/core/module/basename'
13
+ require 'facets/core/string/basename'
14
+ require 'qualitysmith_extensions/module/namespace'
15
+
16
+ class Module
17
+ # Gets the basename of a "module path" (the name of the module without any of the namespace modules that it is contained in),
18
+ # in the same sense that <tt>File.basename</tt> returns the basename of a _filesystem_ path.
19
+ #
20
+ # This is identical to Facets' String#basename ('facets/core/string/basename') except that:
21
+ # * it is a class method instead of an instance method of String,
22
+ # * it accepts modules, strings, and symbols.
23
+ #
24
+ # See also <tt>Module.dirname</tt>/<tt>Module.namespace_name_of</tt>.
25
+ #
26
+ # These can be used together, such that the following is always true:
27
+ # OuterModule::MiddleModule::InnerModule == Module.join(Module.dirname(some_module), Module.basename(some_module)).constantize
28
+ #
29
+ def self.basename(module_or_name)
30
+ case module_or_name
31
+ when Module
32
+ module_or_name.basename
33
+ when Symbol
34
+ module_or_name.to_s.basename
35
+ when String
36
+ module_or_name.basename
37
+ else
38
+ raise ArgumentError
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+
45
+
46
+ # _____ _
47
+ # |_ _|__ ___| |_
48
+ # | |/ _ \/ __| __|
49
+ # | | __/\__ \ |_
50
+ # |_|\___||___/\__|
51
+ #
52
+ =begin test
53
+ require 'test/unit'
54
+
55
+ module OuterModule; end
56
+ module OuterModule::MiddleModule; end
57
+ module OuterModule::MiddleModule::InnerModule; end
58
+
59
+ class BasenameTest < Test::Unit::TestCase
60
+ def test_simple
61
+ assert_equal 'OuterModule', Module.basename(OuterModule)
62
+ assert_equal 'OuterModule', Module.basename(:OuterModule)
63
+ assert_equal 'OuterModule', Module.basename('OuterModule')
64
+ end
65
+ def test_nesting
66
+ assert_equal 'InnerModule',
67
+ Module.basename(OuterModule::MiddleModule::InnerModule)
68
+ assert_equal 'InnerModule',
69
+ Module.basename(:'OuterModule::MiddleModule::InnerModule')
70
+ assert_equal 'InnerModule',
71
+ Module.basename('OuterModule::MiddleModule::InnerModule')
72
+ end
73
+ end
74
+ =end
75
+
76
+
@@ -0,0 +1,497 @@
1
+ #--
2
+ # Author:: Thomas Sawyer, Tyler Rick
3
+ # Copyright:: Copyright (c) Thomas Sawyer, probably, since this is a derivative work
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes
6
+ # Developer notes::
7
+ # * Based on /usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/module/attr_tester.rb
8
+ # * Hey Thomas, don't you think Module#attr_tester should only create the read-only a? method and have another method that creates the writer (like there how we have attr_reader, _writer, and _accessor?) ? "tester" does not imply "setter" in my mind...
9
+ # * I'm going to rename this one to bool_attr_accessor, which calls both bool_attr_reader and bool_attr_writer
10
+ # * Then you also have the option to use bool_attr_reader and bool_attr_writer separately if you so desire.
11
+ # * Other changes made:
12
+ # * Changed it so that if you call a!(false) it would actually set @a to false rather than leaving it unchanged. (I assume that was a bug.)
13
+ #++
14
+
15
+ # bool_attr_accessor
16
+
17
+ class Module
18
+ # This creates a reader method for a boolean (flag) attribute (instance variable).
19
+ #
20
+ # bool_attr_reader :a
21
+ #
22
+ # is equivalent to
23
+ #
24
+ # def a?
25
+ # @a ? true : @a
26
+ # end
27
+ #
28
+ # Example:
29
+ # class Foo
30
+ # def set_it
31
+ # @a = true
32
+ # end
33
+ # end
34
+ # x = Foo.new
35
+ # x.a? # => false
36
+ # x.set_it
37
+ # x.a? # => true
38
+ #
39
+ def bool_attr_reader(*args)
40
+ options = (if args.last.is_a?(Hash) then args.pop else {} end) # These options aren't used here, per se, but it allows us to have bool_attr_accessor pass along same args to both bool_attr_reader and bool_attr_setter.
41
+
42
+ make = {}
43
+ args.each { |a|
44
+ make["#{a}?".to_sym] = %{
45
+ def #{a}?(true_value=true)
46
+ @#{a} ? true_value : @#{a}
47
+ end
48
+ }
49
+ }
50
+ module_eval make.values.join("\n"), __FILE__, __LINE__
51
+
52
+ make.keys
53
+ end
54
+
55
+ # This creates a setter method for a boolean (flag) attribute (instance variable).
56
+ #
57
+ # bool_attr_setter :a
58
+ #
59
+ # is equivalent to
60
+ #
61
+ # def a!(switch=Exception)
62
+ # if switch == Exception
63
+ # @a = !@a
64
+ # else
65
+ # @a = switch ? true : false
66
+ # self
67
+ # end
68
+ # end
69
+ #
70
+ # This setter method can either be used to set it directly to true or false or to toggle it.
71
+ #
72
+ # Examples:
73
+ # x = Klass.new
74
+ # x.a! true # sets @a to true
75
+ # x.a! # toggles @a, so that it ends up being false
76
+ # x.a! # toggles @a, so that it ends up being true
77
+ # x.a! false # sets @a to false
78
+ #
79
+ # Use <tt>:allow_nil</tt> if you want it to be a tri-state flag -- that is, if you need to be able to set it to +nil+ as well as true and false.
80
+ # bool_attr_setter :a, :b, :allow_nil => true
81
+ # x.a! nil # sets @a to nil
82
+ #
83
+ def bool_attr_setter(*args)
84
+ options = (if args.last.is_a?(Hash) then args.pop else {} end)
85
+
86
+ make = {}
87
+ args.each { |a|
88
+ make["#{a}!".to_sym] = %{
89
+ def #{a}!(switch=Exception)
90
+ if switch == Exception
91
+ @#{a} = !@#{a}
92
+ else
93
+ #{
94
+ options[:allow_nil] ?
95
+ "@#{a} = switch ? true : switch" :
96
+ "@#{a} = switch ? true : false"
97
+ }
98
+ self
99
+ end
100
+ end
101
+ }
102
+ }
103
+ module_eval make.values.join("\n"), __FILE__, __LINE__
104
+ make.keys
105
+ end
106
+
107
+
108
+ # This creates both a reader and a setter for a boolean (flag) attribute (instance variable).
109
+ #
110
+ # bool_attr_accessor :a
111
+ #
112
+ # is equivalent to
113
+ #
114
+ # bool_attr_reader :a
115
+ # bool_attr_setter :a
116
+ #
117
+ # Examples:
118
+ # x = Klass.new
119
+ # x.a! true # sets @a to true
120
+ # x.a? # => true
121
+ # x.a! # toggles @a, so that it ends up being false
122
+ # x.a! # toggles @a, so that it ends up being true
123
+ # x.a! false # sets @a to false
124
+ #
125
+ def bool_attr_accessor(*args)
126
+ bool_attr_reader *args
127
+ bool_attr_setter *args
128
+ end
129
+
130
+ end
131
+
132
+ # mbool_attr_accessor
133
+
134
+ class Module
135
+ # This creates a reader method for a boolean (flag) class/module variable.
136
+ #
137
+ # mbool_attr_reader :a
138
+ #
139
+ # is equivalent to
140
+ #
141
+ # def self.a?
142
+ # @@a ? true : @@a
143
+ # end
144
+ #
145
+ # Works for both classes and modules.
146
+ #
147
+ def mbool_attr_reader(*args)
148
+ options = (if args.last.is_a?(Hash) then args.pop else {} end) # These options aren't used here, per se, but it allows us to have bool_attr_accessor pass along same args to both bool_attr_reader and bool_attr_setter.
149
+
150
+ make = {}
151
+ args.each { |a|
152
+ make["#{a}?".to_sym] = %{
153
+ def self.#{a}?(true_value=true)
154
+ @@#{a} ? true_value : @@#{a}
155
+ end
156
+ }
157
+ }
158
+ module_eval make.values.join("\n"), __FILE__, __LINE__
159
+ make.keys
160
+ end
161
+
162
+ # This creates a setter method for a boolean (flag) class/module variable.
163
+ #
164
+ # mbool_attr_setter :a
165
+ #
166
+ # is equivalent to
167
+ #
168
+ # def self.a!(switch=Exception)
169
+ # if switch == Exception
170
+ # @@a = !@@a
171
+ # else
172
+ # @@a = switch ? true : false
173
+ # self
174
+ # end
175
+ # end
176
+ #
177
+ # Works for both classes and modules.
178
+ #
179
+ # Use <tt>:allow_nil</tt> if you want it to be a tri-state flag -- that is, if you need to be able to set it to +nil+ as well as true and false.
180
+ # mbool_attr_setter :a, :b, :allow_nil => true
181
+ # C.a! nil # sets @@a to nil
182
+ #
183
+ def mbool_attr_setter(*args)
184
+ options = (if args.last.is_a?(Hash) then args.pop else {} end)
185
+
186
+ make = {}
187
+ args.each { |a|
188
+ # Initialize it first so that we won't have any NameErrors.
189
+ module_eval %{ @@#{a} = nil if !defined?(@@#{a}) }, __FILE__, __LINE__
190
+
191
+ make["#{a}!".to_sym] = %{
192
+ def self.#{a}!(switch=Exception)
193
+ if switch == Exception
194
+ @@#{a} = !@@#{a}
195
+ else
196
+ #{
197
+ options[:allow_nil] ?
198
+ "@@#{a} = switch ? true : switch" :
199
+ "@@#{a} = switch ? true : false"
200
+ }
201
+ self
202
+ end
203
+ end
204
+ }
205
+ }
206
+ module_eval make.values.join("\n"), __FILE__, __LINE__
207
+ make.keys
208
+ end
209
+
210
+ # This creates both a reader and a setter for a boolean (flag) class/module variable.
211
+ #
212
+ # mbool_attr_accessor :a
213
+ #
214
+ # is equivalent to
215
+ #
216
+ # mbool_attr_reader :a
217
+ # mbool_attr_setter :a
218
+ #
219
+ # Works for both classes and modules.
220
+ #
221
+ def mbool_attr_accessor(*args)
222
+ mbool_attr_reader *args
223
+ mbool_attr_setter *args
224
+ end
225
+ end
226
+
227
+
228
+
229
+ # _____ _
230
+ # |_ _|__ ___| |_
231
+ # | |/ _ \/ __| __|
232
+ # | | __/\__ \ |_
233
+ # |_|\___||___/\__|
234
+ #
235
+ =begin test
236
+ require 'test/unit'
237
+ require 'rubygems'
238
+ require 'qualitysmith_extensions/object/ignore_access'
239
+
240
+ #---------------------------------------------------------------------------------------------------
241
+ # Test that it works for *instances*
242
+ class TestBoolAttr < Test::Unit::TestCase
243
+
244
+ class C
245
+ bool_attr_accessor :a, :b
246
+ end
247
+
248
+ def setup
249
+ @x = C.new
250
+ end
251
+
252
+ # Also tests that it can create multiple accessors at once.
253
+ def test1_default_is_nil
254
+ assert_equal nil, C.new.a?
255
+ assert_equal nil, C.new.b?
256
+ end
257
+
258
+ def test2_toggle
259
+ assert_equal nil, @x.a?
260
+ @x.a!
261
+ assert_equal true, @x.a?
262
+ @x.a!
263
+ assert_equal false, @x.a?
264
+ end
265
+
266
+ def test3_setter
267
+ @x.a! true
268
+ @x.a! true
269
+ assert_equal true, @x.a?
270
+
271
+ @x.a! false
272
+ assert_equal false, @x.a?
273
+ end
274
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
275
+ @x.a! "whatever"
276
+ assert_equal true, @x.a? # Still returns a boolean even though we tried to set it to a string.
277
+
278
+ @x.a! nil
279
+ assert_equal false, @x.a? # Still returns a boolean even though we tried to set it to nil.
280
+ end
281
+
282
+ end
283
+
284
+ class TestBoolAttr_AllowNil < Test::Unit::TestCase
285
+
286
+ class C
287
+ bool_attr_accessor :a, :b, :allow_nil => true
288
+ end
289
+
290
+ def setup
291
+ @x = C.new
292
+ end
293
+
294
+ def test1_default_is_nil
295
+ assert_equal nil, C.new.a?
296
+ assert_equal nil, C.new.b?
297
+ end
298
+
299
+ def test2_for_nilability
300
+ @x.a! "whatever"
301
+ assert_equal true, @x.a? # Still returns a boolean even though we tried to set it to a string.
302
+
303
+ @x.a! nil
304
+ assert_equal nil, @x.a? # Lets us set it to nil!
305
+ #assert_equal true, @x.a?(nil) # Testing the "is it nil?" question.
306
+ assert_equal true, @x.a?.nil? # Testing the "is it nil?" question.
307
+
308
+
309
+ @x.a! false
310
+ assert_equal false, @x.a? # Lets us set it to false!
311
+ assert_equal true, @x.a? == false # Testing the "is it false?" question.
312
+ end
313
+ end
314
+
315
+
316
+
317
+ #---------------------------------------------------------------------------------------------------
318
+ # Test that it works for *modules*
319
+ class TestForModules < Test::Unit::TestCase
320
+
321
+ class M_for_default_is_nil
322
+ mbool_attr_accessor :a
323
+ end
324
+ def test1_default_is_nil
325
+ assert_equal nil, M_for_default_is_nil.a?
326
+ end
327
+
328
+ module M
329
+ mbool_attr_accessor :a
330
+ end
331
+ def test2_toggle
332
+ assert_equal nil, M.a?
333
+ M.a!
334
+ assert_equal true, M.a?
335
+ M.a!
336
+ assert_equal false, M.a?
337
+ end
338
+ def test3_setter
339
+ M.a! true
340
+ M.a! true
341
+ assert_equal true, M.a?
342
+
343
+ M.a! false
344
+ assert_equal false, M.a?
345
+ end
346
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
347
+ M.a! "whatever"
348
+ assert_equal true, M.a? # Still returns a boolean even though we tried to set it to a string.
349
+
350
+ M.a! nil
351
+ assert_equal false, M.a? # Still returns a boolean even though we tried to set it to nil.
352
+ end
353
+ end
354
+ class TestForModules_AllowNil < Test::Unit::TestCase
355
+
356
+ module M
357
+ mbool_attr_accessor :a, :b, :allow_nil => true
358
+ end
359
+
360
+ def test1_default_is_nil
361
+ assert_equal nil, M.a?
362
+ assert_equal nil, M.b?
363
+ end
364
+
365
+ def test2_for_nilability
366
+ M.a! "whatever"
367
+ assert_equal true, M.a? # Still returns a boolean even though we tried to set it to a string.
368
+
369
+ M.a! nil
370
+ assert_equal nil, M.a? # Lets us set it to nil!
371
+ #assert_equal true, M.a?(nil) # Testing the "is it nil?" question.
372
+ assert_equal true, M.a?.nil? # Testing the "is it nil?" question.
373
+
374
+
375
+ M.a! false
376
+ assert_equal false, M.a? # Lets us set it to false!
377
+ assert_equal true, M.a? == false # Testing the "is it false?" question.
378
+ end
379
+ end
380
+
381
+ #---------------------------------------------------------------------------------------------------
382
+ # Test that it also works for *classes*
383
+ class TestForClasses < Test::Unit::TestCase
384
+
385
+ class C_for_default_is_nil
386
+ mbool_attr_accessor :a
387
+ end
388
+ def test1_default_is_nil
389
+ assert_equal nil, C_for_default_is_nil.a?
390
+ end
391
+
392
+ class C
393
+ mbool_attr_accessor :a
394
+ end
395
+
396
+ def test2_toggle
397
+ C.access.class_variable_set :@@a, false
398
+ assert_equal false, C.a? # otherwise would have been nil
399
+ C.a!
400
+ assert_equal true, C.a?
401
+ C.a!
402
+ assert_equal false, C.a?
403
+
404
+ assert_equal ["@_ignore_access_functor"], C.instance_variables
405
+ assert_equal ["@@a"], C.class_variables
406
+ end
407
+
408
+ def test3_setter
409
+ C.a! true
410
+ C.a! true
411
+ assert_equal true, C.a?
412
+
413
+ C.a! false
414
+ assert_equal false, C.a?
415
+ end
416
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
417
+ C.a! "whatever"
418
+ assert_equal true, C.a? # Still returns a boolean even though we tried to set it to a string.
419
+
420
+ C.a! nil
421
+ assert_equal false, C.a? # Still returns a boolean even though we tried to set it to nil.
422
+ end
423
+ end
424
+
425
+
426
+ # Observation: You can also the normal bool_attr_accessor in conjunction with class << self.
427
+ # The methods generated seem to *behave* in the same way. Both techniques allow you to query the class (C.a?).
428
+ # The only difference is in which *variables* are use to store the state:
429
+ # * class << self and the normal bool_attr_accessor:
430
+ # Stores the state in an instance variable for the *class*: @a
431
+ # * mbool_attr_accessor:
432
+ # Stores the state in a *class* variable: @@a
433
+ #
434
+ # Can someone explain to me the difference between class variables and instance variables of a class?
435
+ # It seems silly (confusing even!) to have both of them!
436
+ #
437
+ # My best explanation is that the fact that we can even *have* instance variables of a class does *not* mean it's a good idea
438
+ # to use them. It simply means that Matz made the language with as few arbitrary restrictions as possible. He made it
439
+ # technically *possible* to do a lot of things that it is probably not good practice to do... And one of those things is
440
+ # using instance variables of classes to store state information for that class.
441
+ #
442
+ # What do you think class variables are for? Exactly that! There's a *reason* we have both @a and @@a variables -- to
443
+ # *differentiate* between the two kinds of variables and keep programmers sane. So please don't blur the distinction and
444
+ # use the @a-type variable to do the job that @@a-type variables are for.
445
+ #
446
+ # Or am I missing something here?
447
+ #
448
+ class TestWith_class_self_and_plain_bool_attr_accessor < Test::Unit::TestCase
449
+
450
+ class C_for_default_is_nil
451
+ class << self
452
+ bool_attr_accessor :a
453
+ end
454
+ end
455
+ def test1_default_is_nil
456
+ assert_equal nil, C_for_default_is_nil.a?
457
+ end
458
+
459
+ class C
460
+ class << self
461
+ bool_attr_accessor :a
462
+ end
463
+ end
464
+ # This is where I spotted a class that uses this technique:
465
+ # * Test::Unit::Assertions::AssertionMessage
466
+
467
+ def test_2_toggle
468
+ assert_equal false, C.a? # Why isn't it nil like it is for the instance use case of bool_attr_accessor?
469
+ C.a!
470
+ assert_equal true, C.a?
471
+ C.a!
472
+ assert_equal false, C.a?
473
+
474
+ assert_equal ["@a"], C.instance_variables
475
+ assert_equal [], C.new.instance_variables # @a is an instance variable of the *class* *not* objects of the class -- weird!
476
+ assert_equal [], C.class_variables
477
+ end
478
+
479
+ def test3_setter
480
+ C.a! true
481
+ C.a! true
482
+ assert_equal true, C.a?
483
+
484
+ C.a! false
485
+ assert_equal false, C.a?
486
+ end
487
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
488
+ C.a! "whatever"
489
+ assert_equal true, C.a? # Still returns a boolean even though we tried to set it to a string.
490
+
491
+ C.a! nil
492
+ assert_equal false, C.a? # Still returns a boolean even though we tried to set it to nil.
493
+ end
494
+
495
+ end
496
+ =end
497
+