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