quality_extensions 0.1.1

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