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,87 @@
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
+ #++
8
+
9
+ class Object
10
+
11
+ def class_methods(include_super = true)
12
+ (
13
+ methods(include_super) \
14
+ - instance_methods
15
+ ).
16
+ sort
17
+ end
18
+ alias_method :module_methods, :class_methods
19
+
20
+ end
21
+
22
+
23
+ # _____ _
24
+ # |_ _|__ ___| |_
25
+ # | |/ _ \/ __| __|
26
+ # | | __/\__ \ |_
27
+ # |_|\___||___/\__|
28
+ #
29
+ =begin test
30
+ require 'test/unit'
31
+ require 'qualitysmith_extensions/test/assert_anything'
32
+ require 'set'
33
+
34
+ module M
35
+ def instance_meth; end
36
+ def self.module_meth; end
37
+ end
38
+ class C
39
+ def instance_meth; end
40
+ def self.module_meth; end
41
+ end
42
+ class CSub < C
43
+ def sub_instance_meth; end
44
+ def self.sub_module_meth; end
45
+ end
46
+
47
+
48
+ class TheTest < Test::Unit::TestCase
49
+ C_common_instance_methods = ['object_id', 'dup', 'send', 'is_a?']
50
+ C_common_class_methods = ['instance_methods']
51
+ def test_class
52
+ assert_subset? (['instance_meth'] + C_common_instance_methods).to_set,
53
+ C.instance_methods.to_set
54
+ assert_subset? (['module_meth'] + C_common_class_methods).to_set,
55
+ C.class_methods.to_set
56
+ end
57
+ def test_class__no_super
58
+ assert_subset? ['instance_meth'].to_set,
59
+ C.instance_methods(false).to_set
60
+ assert_subset? ['module_meth'].to_set,
61
+ C.class_methods(false).to_set
62
+ end
63
+
64
+ def test_module
65
+ assert_equal ['instance_meth'], M.instance_methods # Unlike a class, modules don't have all the common instance methods from Object
66
+ assert_subset? (['module_meth'] + C_common_class_methods).to_set,
67
+ M.class_methods.to_set
68
+ end
69
+ def test_module__no_super
70
+ assert_equal ['instance_meth'], M.instance_methods(false) # Unlike a class, modules don't have all the common instance methods from Object
71
+ assert_subset? (['module_meth']).to_set,
72
+ M.class_methods(false).to_set
73
+ end
74
+
75
+ def test_subclass
76
+ assert_subset? (['instance_meth', 'sub_instance_meth'] + C_common_instance_methods).to_set,
77
+ CSub.instance_methods.to_set
78
+ assert_subset? ['module_meth', 'sub_module_meth'].to_set,
79
+ CSub.class_methods.to_set
80
+ end
81
+ def test_subclass__no_super
82
+ assert_equal ['sub_instance_meth'], CSub.instance_methods(false)
83
+ assert_equal ['sub_module_meth'], CSub.class_methods(false)
84
+ end
85
+ end
86
+ =end
87
+
@@ -0,0 +1,315 @@
1
+ #--
2
+ # Author:: Aaron Pfeifer, Neil Abraham, Tyler Rick
3
+ # Copyright:: Copyright (c) 2006-2007 Aaron Pfeifer & Neil Abraham
4
+ # License:: MIT License
5
+ # Submit to Facets?:: Yes!
6
+ # Developer notes::
7
+ # * Why are we calling it create? Why not just new? Would that cause any problems?
8
+ # To do::
9
+ # * Submit to pluginaweek mailing list
10
+ # Changes:
11
+ # r2964 (Tyler):
12
+ # * Started from http://svn.pluginaweek.org/trunk/plugins/ruby/module/module_creation_helper/ (Last Changed Rev: 320)
13
+ # * Renamed :parent option to :namespace. (:parent is still allowed for backwards compatibility)
14
+ # * Changed examples and tests to pass in the name as a symbol instead of a string.
15
+ # * Made it so you can pass in the namespace as part of the name if you want: Module.create(:'Foo::Bar') instead of Module.create(:Foo, :parent => Bar)
16
+ # * Added to the documentation
17
+ # * Added new tests
18
+ # * test_with_block_2
19
+ # * test_nested_class_with_superclass_with_same_name
20
+ # * test_referencing_a_namespace_that_isnt_defined
21
+ # * test_creating_a_class_more_than_once
22
+ # * test_using_return_value_of_one_create_within_another_create
23
+ # * Added __FILE__, __LINE__ to class_eval so that error messages would be more helpful.
24
+ #++
25
+
26
+ require 'rubygems'
27
+ require 'facets/core/hash/assert_has_only_keys'
28
+ require 'facets/core/hash/reverse_merge'
29
+ require 'facets/core/kernel/constant'
30
+ require 'facets/core/symbol/to_proc'
31
+ require 'qualitysmith_extensions/module/split'
32
+ require 'qualitysmith_extensions/module/basename'
33
+ require 'qualitysmith_extensions/module/dirname'
34
+
35
+ class Module
36
+ # Creates a new module with the specified name. This is essentially the
37
+ # same as actually defining the module like so:
38
+ #
39
+ # module NewModule
40
+ # end
41
+ #
42
+ # or as a class:
43
+ #
44
+ # class NewClass < SuperKlass
45
+ # end
46
+ #
47
+ # Configuration options:
48
+ # <tt>superclass</tt> - The class to inherit from. This only applies when using Class#create. Default is Object.
49
+ # <tt>namespace</tt>/<tt>parent</tt> - The class/module namespace that contains this module. Default is Object.
50
+ #
51
+ # You can also include the namespace in the +name+ if you'd prefer. For instance, name = <tt>:'Foo::Bar'</tt> is the same as specifying <tt>name = :Bar, :namespace => Foo</tt>. (Note: The namespace module specified must already be defined, just like it would have to be defined if you used the <tt>:namespace</tt> option.)
52
+ #
53
+ # Examples:
54
+ #
55
+ # Module.create(:Foo) # => Foo
56
+ # Module.create(:'Foo::Bar', :namespace => Foo) # => Foo::Bar
57
+ # Module.create(:Bar, :namespace => Foo) # => Foo::Bar
58
+ #
59
+ # Class.create(:Base) # => Base
60
+ # Class.create(:'Foo::Klass', :superclass => Base) # => Foo::Klass
61
+ #
62
+ # Unlike the built-in Ruby +module+/+class+ directive, this actually returns the newly created module/class as the return value. So, for example, you can do things like this:
63
+ #
64
+ # klass = Class.create(:'Foo::Klass', :superclass => Class.create(:Base)) # => Foo::Klass
65
+ # klass.name # => Foo::Klass
66
+ # klass.superclass # => Base
67
+ #
68
+ # You can also pass a block to create. This:
69
+ #
70
+ # Class.create(:ClassWithBlock, :superclass => BaseClass) do
71
+ # def self.say_hello
72
+ # 'hello'
73
+ # end
74
+ # end
75
+ #
76
+ # is equivalent to this:
77
+ #
78
+ # class ClassWithBlock < BaseClass do
79
+ # def self.say_hello
80
+ # 'hello'
81
+ # end
82
+ # end
83
+ #
84
+ def create(name, options = {}, &block)
85
+ # Validate arguments
86
+ raise ArgumentError unless name.respond_to?(:to_s)
87
+ options[:namespace] = options.delete(:parent) if options.has_key?(:parent)
88
+ options.assert_has_only_keys(
89
+ :superclass,
90
+ :namespace
91
+ )
92
+ module_or_class = self.to_s.downcase
93
+ raise ArgumentError, 'Modules cannot have superclasses' if options[:superclass] && module_or_class == 'module'
94
+
95
+ # Set defaults
96
+ namespace_module, superclass =
97
+ options[:namespace] || ::Object,
98
+ options[:superclass] || ::Object
99
+
100
+ # Determine the namespace to create it in
101
+ nesting = Module.split_name(name)
102
+ if nesting.size > 1
103
+ namespace_module = Module.namespace_of(name) # For example, would be A::B for A::B::C
104
+ base_name = Module.basename(name) # For example, would be :C for A::B::C
105
+ else
106
+ base_name = name
107
+ end
108
+
109
+ # Actually create the new module
110
+ if superclass != ::Object
111
+ superclass = " < ::#{superclass}"
112
+ else
113
+ superclass = ''
114
+ end
115
+ namespace_module.class_eval <<-end_eval, __FILE__, __LINE__
116
+ #{module_or_class} #{base_name}#{superclass}
117
+ # Empty
118
+ end
119
+ end_eval
120
+ our_new_module = namespace_module.const_get(base_name)
121
+
122
+ our_new_module.class_eval(&block) if block_given?
123
+ our_new_module
124
+ end
125
+ end
126
+
127
+
128
+
129
+
130
+ # _____ _
131
+ # |_ _|__ ___| |_
132
+ # | |/ _ \/ __| __|
133
+ # | | __/\__ \ |_
134
+ # |_|\___||___/\__|
135
+ #
136
+ =begin test
137
+ require 'test/unit'
138
+ require 'rubygems'
139
+ require 'qualitysmith_extensions/module/attribute_accessors'
140
+ require 'qualitysmith_extensions/module/namespace'
141
+ require 'qualitysmith_extensions/symbol/constantize'
142
+ require 'facets/core/module/basename'
143
+
144
+ module Namespace
145
+ end
146
+
147
+ class BaseClass
148
+ cattr_accessor :test_name
149
+ cattr_accessor :test_inspect
150
+ cattr_accessor :test_to_s
151
+
152
+ def self.inherited(base)
153
+ self.test_name = base.name
154
+ self.test_inspect = base.inspect
155
+ self.test_to_s = base.to_s
156
+ end
157
+ end
158
+
159
+ class ModuleCreationHelperTest < Test::Unit::TestCase
160
+ def setup
161
+ BaseClass.test_name = nil
162
+ BaseClass.test_inspect = nil
163
+ BaseClass.test_to_s = nil
164
+ end
165
+
166
+ def test_no_options_for_class
167
+ klass = Class.create(:Foo)
168
+ assert_equal Object, klass.superclass
169
+ assert_equal Object, klass.namespace_module
170
+ assert Object.const_defined?('Foo')
171
+ end
172
+
173
+ def test_no_options_for_module
174
+ mod = Module.create(:FooMod)
175
+ assert_equal Object, mod.namespace_module
176
+ assert Object.const_defined?('FooMod')
177
+ end
178
+
179
+ def test_invalid_option
180
+ assert_raise(ArgumentError) {Class.create(nil, :invalid => true)}
181
+ end
182
+
183
+ def test_superclass_for_module
184
+ assert_raise(ArgumentError) {Module.create(nil, :superclass => Object)}
185
+ end
186
+
187
+ def test_superclass
188
+ klass = Class.create(:Bar, :superclass => BaseClass)
189
+ assert_equal BaseClass, klass.superclass
190
+ assert_equal Object, klass.namespace_module
191
+ assert Object.const_defined?('Bar')
192
+ end
193
+
194
+ def test_namespace_for_class
195
+ klass = Class.create(:Baz, :namespace => Namespace)
196
+ assert_equal Object, klass.superclass
197
+ assert_equal Namespace, klass.namespace_module
198
+ assert Namespace.const_defined?('Baz')
199
+ end
200
+
201
+ def test_namespace_for_class__namespace_as_part_of_name
202
+ klass = Class.create(:'Namespace::Baz')
203
+ assert_equal Object, klass.superclass
204
+ assert_equal Namespace, klass.namespace_module
205
+ assert Namespace.const_defined?('Baz')
206
+ end
207
+
208
+ def test_namespace_for_module
209
+ mod = Module.create(:BazMod, :namespace => Namespace)
210
+ assert_equal Namespace, mod.namespace_module
211
+ assert Namespace.const_defined?('BazMod')
212
+ end
213
+
214
+ def test_superclass_and_namespace
215
+ klass = Class.create(:Biz, :superclass => BaseClass, :namespace => Namespace)
216
+ assert_equal BaseClass, klass.superclass
217
+ assert_equal Namespace, klass.namespace_module
218
+ assert Namespace.const_defined?('Biz')
219
+ end
220
+
221
+ def test_name_before_evaluated
222
+ klass = Class.create(:Waddle, :superclass => BaseClass)
223
+ assert_equal 'Waddle', BaseClass.test_name
224
+ end
225
+
226
+ def test_inspect_before_evaluated
227
+ klass = Class.create(:Widdle, :superclass => BaseClass)
228
+ assert_equal 'Widdle', BaseClass.test_inspect
229
+ end
230
+
231
+ def test_to_s_before_evaluated
232
+ klass = Class.create(:Wuddle, :superclass => BaseClass)
233
+ assert_equal 'Wuddle', BaseClass.test_to_s
234
+ end
235
+
236
+ def test_name_before_evaluated_with_namespace
237
+ klass = Class.create(:Waddle, :superclass => BaseClass, :namespace => Namespace)
238
+ assert_equal 'Namespace::Waddle', BaseClass.test_name
239
+ end
240
+
241
+ def test_inspect_before_evaluated_with_namespace
242
+ klass = Class.create(:Widdle, :superclass => BaseClass, :namespace => Namespace)
243
+ assert_equal 'Namespace::Widdle', BaseClass.test_inspect
244
+ end
245
+
246
+ def test_to_s_before_evaluated_with_namespace
247
+ klass = klass = Class.create(:Wuddle, :superclass => BaseClass, :namespace => Namespace)
248
+ assert_equal 'Namespace::Wuddle', BaseClass.test_to_s
249
+ end
250
+
251
+ def test_subclass_of_dynamic_class
252
+ klass = Class.create(:Foobar)
253
+ subclass = Class.create(:Foobaz, :superclass => klass)
254
+
255
+ assert_equal klass, subclass.superclass
256
+ assert_equal 'Foobaz', subclass.name
257
+ assert_equal 'Foobaz', subclass.inspect
258
+ assert_equal 'Foobaz', subclass.to_s
259
+ end
260
+
261
+ def test_with_block_1
262
+ klass = Class.create(:ClassWithBlock, :superclass => BaseClass) do
263
+ def self.say_hello
264
+ 'hello'
265
+ end
266
+ end
267
+ assert_equal 'hello', ClassWithBlock.say_hello
268
+ end
269
+
270
+ def test_with_block_2
271
+ klass = Class.create(:ClassWithBlock, :superclass => BaseClass) do
272
+ def say_hello
273
+ 'hello'
274
+ end
275
+ end
276
+ assert_equal 'hello', ClassWithBlock.new.say_hello
277
+ end
278
+
279
+ def test_nested_class_with_superclass_with_same_name
280
+ klass = Class.create(:Employee)
281
+ nested_class = Class.create(:Employee, :superclass => klass, :namespace => Namespace)
282
+ assert_equal klass, nested_class.superclass
283
+ assert_equal klass.basename, nested_class.basename
284
+ end
285
+
286
+ def test_nested_class_with_superclass_with_same_name
287
+ klass = Class.create(:Employee)
288
+ nested_class = Class.create(:Employee, :superclass => klass, :namespace => Namespace)
289
+ assert_equal klass, nested_class.superclass
290
+ assert_equal klass.basename, nested_class.basename
291
+ end
292
+
293
+ def test_referencing_a_namespace_that_isnt_defined
294
+ assert_raise(NameError) { Class.create(:'Zzt::Klass') }
295
+ end
296
+
297
+ def test_creating_a_class_more_than_once
298
+ klass = Class.create(:'Foo')
299
+ klass = Class.create(:'Foo')
300
+ end
301
+
302
+ def test_using_return_value_of_one_create_within_another_create
303
+ klass = Class.create(:'Foo')
304
+ klass = Class.create(:'Base')
305
+ klass = Class.create(:'Foo::Klass',
306
+ :superclass => Class.create(:Base)
307
+ )
308
+ assert_equal 'Foo::Klass', klass.name
309
+ assert_equal Base, klass.superclass
310
+ end
311
+
312
+
313
+ end
314
+ =end
315
+
@@ -0,0 +1,9 @@
1
+ #create_setter/constructor :_F, :filename
2
+ #create_setter/constructor :initialize, :filename do
3
+ # extra constructor stuff
4
+ #end
5
+ #
6
+ # def _F(filename)
7
+ # @filename = filename
8
+ # end
9
+ #
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ # Alias for:
3
+ require 'qualitysmith_extensions/module/namespace'
4
+
@@ -0,0 +1,312 @@
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
+ # * Is it thread-safe?? Probably not, as it stands...
8
+ # But the whole thing that prompted me to create a guard method in the first place was to try to avoid a deadlock that was
9
+ # caused by recursively calling a method with a synchronize in it (in other words, someone else's attempt at thread-safety
10
+ # resulted in me getting into a deadlock, which is why I wrote this method to begin with). So I'm not even sure if it's
11
+ # possible to make it thread-safe?
12
+ #++
13
+
14
+ require 'rubygems'
15
+ require 'qualitysmith_extensions/module/attribute_accessors'
16
+ require 'facets/core/kernel/require_local'
17
+ require_local 'bool_attr_accessor'
18
+ #require 'qualitysmith_extensions/module/bool_attr_accessor'
19
+ require 'qualitysmith_extensions/symbol/match'
20
+
21
+
22
+ class Module
23
+ # A guard method (by this definition anyway) is a method that sets a flag, executes a block, and then returns the flag to its
24
+ # previous value. It ensures that the flag is set during the execution of the block.
25
+ #
26
+ # In the simplest case, you'd use it like this:
27
+ # class A
28
+ # guard_method :disable_stupid_stuff!, :@stupid_stuff_disabled
29
+ # end
30
+ # a = A.new
31
+ # a.disable_stupid_stuff! do # Causes @stupid_stuff_disabled to be set to true
32
+ # # Section of code during which you don't want any stupid stuff to happen
33
+ # end # Causes @stupid_stuff_disabled to be set back to false
34
+ # # Okay, a, you can resume doing stupid stuff again...
35
+ #
36
+ # If you want your guard method to *disable* the flag rather than *enable* it, simply pass false to the guard method.
37
+ #
38
+ # These calls can be nested however you wish:
39
+ # a.guard_the_fruit! do
40
+ # a.guard_the_fruit!(false) do
41
+ # assert_equal false, a.guarding_the_fruit?
42
+ # end
43
+ # assert_equal true, a.guarding_the_fruit?
44
+ # end
45
+ #
46
+ # You can also use the guard methods as normal flag setter/clearer methods by simply not passing a block to it. Hence
47
+ # a.guard_the_fruit!
48
+ # will simply set @guarding_the_fruit to true, and
49
+ # a.guard_the_fruit!(false)
50
+ # will set @guarding_the_fruit to false.
51
+ #
52
+ def guard_method(guard_method_name, guard_variable)
53
+ raise ArgumentError.new("Expected an instance variable name but got #{guard_variable}") if guard_variable !~ /^@([\w_]+)$/
54
+ guard_variable.to_s =~ /^@([\w_]+)$/ # Why didn't the regexp above set $1 ??
55
+ class_eval do
56
+ bool_attr_accessor $1.to_sym
57
+ end
58
+ module_eval <<-End, __FILE__, __LINE__+1
59
+ def #{guard_method_name}(new_value = true, &block)
60
+ old_guard_state, #{guard_variable} = #{guard_variable}, new_value
61
+ if block_given?
62
+ begin
63
+ returning = yield
64
+ ensure
65
+ #{guard_variable} = old_guard_state
66
+ returning
67
+ end
68
+ end
69
+ end
70
+ End
71
+ end
72
+
73
+ # See the documentation for guard_method. mguard_method does the same thing, only it creates a _class_ (or _module_) method
74
+ # rather than an instance method and it uses a _class_ (or _module_) variable rather than an instance variable to store the
75
+ # guard state.
76
+ #
77
+ # Example:
78
+ # mguard_method :guard_the_fruit!, :@@guarding_the_fruit
79
+ # mguard_method :use_assert_equal_with_highlight!, :@@always_use_assert_equal_with_highlight
80
+ def mguard_method(guard_method_name, guard_variable)
81
+ raise ArgumentError.new("Expected a class variable name but got #{guard_variable}") if guard_variable !~ /^@@[\w_]+$/
82
+ guard_variable.to_s =~ /^@@([\w_]+)$/
83
+ class_eval do
84
+ mbool_attr_accessor $1.to_sym
85
+ end
86
+ module_eval <<-End, __FILE__, __LINE__+1
87
+ class << self
88
+ def #{guard_method_name}(new_value = true, &block)
89
+ old_guard_state, #{guard_variable} = #{guard_variable}, new_value
90
+ if block_given?
91
+ begin
92
+ returning = yield
93
+ ensure
94
+ #{guard_variable} = old_guard_state
95
+ returning
96
+ end
97
+ end
98
+ end
99
+ end
100
+ End
101
+ end
102
+ end
103
+
104
+
105
+ # _____ _
106
+ # |_ _|__ ___| |_
107
+ # | |/ _ \/ __| __|
108
+ # | | __/\__ \ |_
109
+ # |_|\___||___/\__|
110
+ #
111
+ =begin test
112
+ require 'test/unit'
113
+
114
+ class GuardMethodTest_Simple < Test::Unit::TestCase
115
+ class A
116
+ guard_method :guard_the_fruit!, :@guarding_the_fruit
117
+ end
118
+ def test_guard_method
119
+ a = A.new
120
+ assert_equal nil, a.guarding_the_fruit?
121
+ a.guard_the_fruit! do
122
+ # Call it recursively!
123
+ a.guard_the_fruit! do
124
+ assert_equal true, a.guarding_the_fruit?
125
+ end
126
+ assert_equal true, a.guarding_the_fruit? # This is the reason why we have to save the 'old_guard_state'. So that we don't stupidly set it back to false if we still haven't exited from the outermost call to the guard black.
127
+ end
128
+ assert_equal nil, a.guarding_the_fruit?
129
+ end
130
+ def test_guard_method_error
131
+ assert_raise(ArgumentError) do
132
+ self.class.class_eval do
133
+ guard_method :guard_the_fruit!, :@@guarding_the_fruit
134
+ end
135
+ end
136
+ end
137
+ def test_return_value
138
+ assert_equal 'special return value', A.new.guard_the_fruit! { 'special return value' }
139
+ end
140
+
141
+ def try_to_return_prematurely(a)
142
+ a.guard_the_fruit! do
143
+ assert_equal true, a.guarding_the_fruit?
144
+ return 'prematurely'
145
+ end
146
+ end
147
+ def test_guard_method_for_block_that_tries_to_return_prematurely
148
+ a = A.new
149
+ assert_equal nil, a.guarding_the_fruit?
150
+ try_to_return_prematurely(a)
151
+ assert_equal nil, a.guarding_the_fruit?
152
+ end
153
+ end
154
+
155
+ class GuardMethodTest_WithUnguard < Test::Unit::TestCase # (By "unguard" here I mean passing false to the guard method...)
156
+ class A
157
+ guard_method :guard_the_fruit!, :@guarding_the_fruit
158
+ end
159
+ def test_guard_method
160
+ a = A.new
161
+ assert_equal nil, a.guarding_the_fruit?
162
+ a.guard_the_fruit! do
163
+ a.guard_the_fruit! do
164
+ assert_equal true, a.guarding_the_fruit?
165
+
166
+ a.guard_the_fruit! false do
167
+ assert_equal false, a.guarding_the_fruit?
168
+ a.guard_the_fruit! do
169
+ assert_equal true, a.guarding_the_fruit?
170
+ end
171
+ assert_equal false, a.guarding_the_fruit?
172
+ end
173
+
174
+ assert_equal true, a.guarding_the_fruit?
175
+ end
176
+ assert_equal true, a.guarding_the_fruit?
177
+ end
178
+ assert_equal nil, a.guarding_the_fruit?
179
+ end
180
+
181
+ def test_guard_method_with_simple_blockless_toggles
182
+ a = A.new
183
+ assert_equal nil, a.guarding_the_fruit?
184
+ a.guard_the_fruit!
185
+ assert_equal true, a.guarding_the_fruit?
186
+
187
+ a.guarding_the_fruit? do
188
+ assert_equal false, a.guarding_the_fruit?
189
+ a.guard_the_fruit! do
190
+ assert_equal true, a.guarding_the_fruit?
191
+ a.guard_the_fruit! false
192
+ assert_equal false, a.guarding_the_fruit?
193
+ a.guard_the_fruit!
194
+ assert_equal true, a.guarding_the_fruit?
195
+ end
196
+ assert_equal false, a.guarding_the_fruit?
197
+ end
198
+
199
+ assert_equal true, a.guarding_the_fruit?
200
+ end
201
+
202
+ def test_return_value
203
+ assert_equal nil, A.new.guard_the_fruit!
204
+ assert_equal nil, A.new.guard_the_fruit!(false)
205
+ assert_equal 'special return value', A.new.guard_the_fruit! { 'special return value' }
206
+ assert_equal 'special return value', A.new.guard_the_fruit!(false) { 'special return value' }
207
+ end
208
+ end
209
+
210
+ #---------------------------------------------------------------------------------------------------------------------------------
211
+ # Begin duplication
212
+ # The following TestCases are simply duplicates of the previous except that they test mguard_method rather than guard_method
213
+ # The main differenes/substitutions:
214
+ # * @@guarding_the_fruit, rather than @guarding_the_fruit
215
+ # * :'<,'>s/A.new/B/g
216
+ # * :'<,'>s/\<a\>/B/g
217
+
218
+ class MGuardMethodTest_Simple < Test::Unit::TestCase
219
+ class B
220
+ mguard_method :guard_the_fruit!, :@@guarding_the_fruit
221
+ end
222
+ def test_mguard_method
223
+ assert_equal nil, B.guarding_the_fruit?
224
+ B.guard_the_fruit! do
225
+ # Call it recursively!
226
+ B.guard_the_fruit! do
227
+ assert_equal true, B.guarding_the_fruit?
228
+ end
229
+ assert_equal true, B.guarding_the_fruit? # This is the reason why we have to save the 'old_guard_state'. So that we don't stupidly set it back to false if we still haven't exited from the outermost call to the guard black.
230
+ end
231
+ assert_equal nil, B.guarding_the_fruit?
232
+ end
233
+ def test_mguard_method_error
234
+ assert_raise(ArgumentError) do
235
+ self.class.class_eval do
236
+ mguard_method :guard_the_fruit!, :@guarding_the_fruit
237
+ end
238
+ end
239
+ end
240
+ def test_return_value
241
+ assert_equal 'special return value', B.guard_the_fruit! { 'special return value' }
242
+ end
243
+
244
+ def try_to_return_prematurely
245
+ B.guard_the_fruit! do
246
+ assert_equal true, B.guarding_the_fruit?
247
+ return 'prematurely'
248
+ end
249
+ end
250
+ def test_guard_method_for_block_that_tries_to_return_prematurely
251
+ assert_equal nil, B.guarding_the_fruit?
252
+ try_to_return_prematurely
253
+ assert_equal nil, B.guarding_the_fruit?
254
+ end
255
+ end
256
+
257
+ class MGuardMethodTest_WithUnguard < Test::Unit::TestCase
258
+ class B
259
+ mguard_method :guard_the_fruit!, :@@guarding_the_fruit
260
+ end
261
+ def test_guard_method
262
+ assert_equal nil, B.guarding_the_fruit?
263
+ B.guard_the_fruit! do
264
+ B.guard_the_fruit! do
265
+ assert_equal true, B.guarding_the_fruit?
266
+
267
+ B.guard_the_fruit!(false) do
268
+ assert_equal false, B.guarding_the_fruit?
269
+ B.guard_the_fruit! do
270
+ assert_equal true, B.guarding_the_fruit?
271
+ end
272
+ assert_equal false, B.guarding_the_fruit?
273
+ end
274
+
275
+ assert_equal true, B.guarding_the_fruit?
276
+ end
277
+ assert_equal true, B.guarding_the_fruit?
278
+ end
279
+ assert_equal nil, B.guarding_the_fruit?
280
+ end
281
+
282
+ def test_guard_method_with_simple_blockless_toggles
283
+ assert_equal nil, B.guarding_the_fruit?
284
+ B.guard_the_fruit!
285
+ assert_equal true, B.guarding_the_fruit?
286
+
287
+ B.guard_the_fruit!(false) do
288
+ assert_equal false, B.guarding_the_fruit?
289
+ B.guard_the_fruit! do
290
+ assert_equal true, B.guarding_the_fruit?
291
+ B.guard_the_fruit!(false)
292
+ assert_equal false, B.guarding_the_fruit?
293
+ B.guard_the_fruit!
294
+ assert_equal true, B.guarding_the_fruit?
295
+ end
296
+ assert_equal false, B.guarding_the_fruit?
297
+ end
298
+
299
+ assert_equal true, B.guarding_the_fruit?
300
+ end
301
+
302
+ def test_return_value
303
+ assert_equal nil, B.guard_the_fruit!
304
+ assert_equal nil, B.guard_the_fruit!(false)
305
+ assert_equal 'special return value', B.guard_the_fruit! { 'special return value' }
306
+ assert_equal 'special return value', B.guard_the_fruit!(false) { 'special return value' }
307
+ end
308
+ end
309
+ # End duplication
310
+ #---------------------------------------------------------------------------------------------------------------------------------
311
+ =end
312
+