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.
- data/Readme +54 -0
- data/lib/qualitysmith_extensions/all.rb +4 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +44 -0
- data/lib/qualitysmith_extensions/array/classify.rb +97 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +52 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +134 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +66 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +36 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +41 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +96 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/colored/toggleability.rb +62 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.54.rb +748 -0
- data/lib/qualitysmith_extensions/console/command.rb +944 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +40 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +31 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +122 -0
- data/lib/qualitysmith_extensions/dir/each_child.rb +58 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +69 -0
- data/lib/qualitysmith_extensions/enumerable/select_until.rb +4 -0
- data/lib/qualitysmith_extensions/enumerable/select_while.rb +109 -0
- data/lib/qualitysmith_extensions/exception/inspect_with_backtrace.rb +65 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +34 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +110 -0
- data/lib/qualitysmith_extensions/find/select.rb +68 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +153 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +34 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +121 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/autoreload.rb +128 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +71 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +115 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +49 -0
- data/lib/qualitysmith_extensions/kernel/example_printer.rb +81 -0
- data/lib/qualitysmith_extensions/kernel/filter_output.rb +108 -0
- data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
- data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +186 -0
- data/lib/qualitysmith_extensions/kernel/require_local_all.rb +4 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +18 -0
- data/lib/qualitysmith_extensions/kernel/simulate_input.rb +52 -0
- data/lib/qualitysmith_extensions/kernel/trap_chain.rb +61 -0
- data/lib/qualitysmith_extensions/kernel/windows_platform.rb +46 -0
- data/lib/qualitysmith_extensions/module/alias_method.rb +6 -0
- data/lib/qualitysmith_extensions/module/alias_method_chain.rb +165 -0
- data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
- data/lib/qualitysmith_extensions/module/attribute_accessors.rb +49 -0
- data/lib/qualitysmith_extensions/module/basename.rb +76 -0
- data/lib/qualitysmith_extensions/module/bool_attr_accessor.rb +497 -0
- data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
- data/lib/qualitysmith_extensions/module/create.rb +315 -0
- data/lib/qualitysmith_extensions/module/create_setter.rb +9 -0
- data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
- data/lib/qualitysmith_extensions/module/guard_method.rb +312 -0
- data/lib/qualitysmith_extensions/module/includable_once.rb +10 -0
- data/lib/qualitysmith_extensions/module/join.rb +66 -0
- data/lib/qualitysmith_extensions/module/malias_method_chain.rb +92 -0
- data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
- data/lib/qualitysmith_extensions/module/namespace.rb +112 -0
- data/lib/qualitysmith_extensions/module/parents.rb +61 -0
- data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
- data/lib/qualitysmith_extensions/module/split.rb +55 -0
- data/lib/qualitysmith_extensions/month.rb +66 -0
- data/lib/qualitysmith_extensions/mutex/if_available.rb +75 -0
- data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
- data/lib/qualitysmith_extensions/object/default.rb +69 -0
- data/lib/qualitysmith_extensions/object/if_else.rb +157 -0
- data/lib/qualitysmith_extensions/object/ignore_access.rb +84 -0
- data/lib/qualitysmith_extensions/object/mcall.rb +92 -0
- data/lib/qualitysmith_extensions/object/methods.rb +63 -0
- data/lib/qualitysmith_extensions/object/send_if.rb +151 -0
- data/lib/qualitysmith_extensions/object/send_if_not_nil.rb +35 -0
- data/lib/qualitysmith_extensions/object/singleton_send.rb +129 -0
- data/lib/qualitysmith_extensions/regexp/join.rb +111 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +27 -0
- data/lib/qualitysmith_extensions/string/each_char_with_index.rb +41 -0
- data/lib/qualitysmith_extensions/string/md5.rb +29 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +43 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +37 -0
- data/lib/qualitysmith_extensions/string/with_knowledge_of_color.rb +64 -0
- data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
- data/lib/qualitysmith_extensions/symbol/match.rb +157 -0
- data/lib/qualitysmith_extensions/template.rb +33 -0
- data/lib/qualitysmith_extensions/test/all.rb +2 -0
- data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +36 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +37 -0
- data/lib/qualitysmith_extensions/test/difference_highlighting.rb +323 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +31 -0
- data/test/all.rb +16 -0
- 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,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
|
+
|