quality_extensions 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,81 @@
|
|
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
|
+
# * Can anyone think of a better name than put_statement?
|
8
|
+
# * Something more like xmp? sp? stp? xm? putst? -- Too cryptic?
|
9
|
+
# * verbose? -- too ambiguous (that could be the name for xmp, for example)
|
10
|
+
# * xmp: Do the set_trace_func trick that irb_xmp/of_caller both use... so that the user doesn't have to pass in the local binding manually...
|
11
|
+
# * Add class method for ExamplePrinter to set a template for use by xmp? So if you don't like the default ("=> #{result}"), you can specify your own...
|
12
|
+
#++
|
13
|
+
|
14
|
+
require 'rubygems'
|
15
|
+
#require 'facets/core/binding/self/of_caller'
|
16
|
+
|
17
|
+
# This was written because the irb/xmp that was already available seemed to be
|
18
|
+
# needlessly complex and needlessly dependent upon "irb" stuff. This
|
19
|
+
# alternative is dirt simple, and it still works.
|
20
|
+
module ExamplePrinter
|
21
|
+
# Prints the given statement (+code+ -- a string) before evaluating it.
|
22
|
+
# Same as xmp only it doesn't print the return value.
|
23
|
+
#
|
24
|
+
# o = nil
|
25
|
+
# xmp 'o = C.new', binding
|
26
|
+
# # => o = C.new
|
27
|
+
def put_statement(code, binding = nil, file = __FILE__, line = __LINE__)
|
28
|
+
# # This didn't work. Still got this error: undefined local variable or method `x' for #<TheTest:0xb7dbc358> (NameError)
|
29
|
+
# Binding.of_caller do |caller_binding|
|
30
|
+
# #puts caller_binding
|
31
|
+
# puts code
|
32
|
+
# eval code, caller_binding
|
33
|
+
# end
|
34
|
+
puts code
|
35
|
+
eval code, binding, file, line
|
36
|
+
end
|
37
|
+
alias_method :stp, :put_statement
|
38
|
+
|
39
|
+
# Prints the given statement (+code+ -- a string) before evaluating it. Then prints its return value.
|
40
|
+
# Pretty much compatible with irb/xmp. But you have currently have to pass
|
41
|
+
# in the binding manually if you have any local variables/methods that xmp
|
42
|
+
# should have access to.
|
43
|
+
def xmp(code, binding = nil)
|
44
|
+
result = put_statement(code, binding)
|
45
|
+
puts "=> #{result}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
include ExamplePrinter
|
50
|
+
|
51
|
+
# _____ _
|
52
|
+
# |_ _|__ ___| |_
|
53
|
+
# | |/ _ \/ __| __|
|
54
|
+
# | | __/\__ \ |_
|
55
|
+
# |_|\___||___/\__|
|
56
|
+
#
|
57
|
+
=begin test
|
58
|
+
require 'test/unit'
|
59
|
+
require 'rubygems'
|
60
|
+
gem 'qualitysmith_extensions'
|
61
|
+
require 'qualitysmith_extensions/kernel/capture_output'
|
62
|
+
require 'facets/core/string/margin'
|
63
|
+
|
64
|
+
class TheTest < Test::Unit::TestCase
|
65
|
+
def test_puts_statement
|
66
|
+
result = nil
|
67
|
+
x = 1
|
68
|
+
output = capture_output { result = put_statement("3 + x", binding) }
|
69
|
+
assert_equal 4, result
|
70
|
+
assert_equal "3 + x", output.chomp
|
71
|
+
end
|
72
|
+
def test_xmp
|
73
|
+
x = 1
|
74
|
+
output = capture_output { xmp("3 + x", binding) }
|
75
|
+
assert_equal <<-End.margin, output.chomp
|
76
|
+
|3 + x
|
77
|
+
|=> 4
|
78
|
+
End
|
79
|
+
end
|
80
|
+
end
|
81
|
+
=end
|
@@ -0,0 +1,108 @@
|
|
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
|
+
require 'stringio'
|
10
|
+
|
11
|
+
# Applies +filter+ to any $stderr output that +block+ tries to generate.
|
12
|
+
#
|
13
|
+
# +filter+ should be a Proc that accepts +attempted_output+ as its parameter and returns the string that should _actually_ be output.
|
14
|
+
#
|
15
|
+
# filter_stderr(lambda{''}) do
|
16
|
+
# noisy_command
|
17
|
+
# end
|
18
|
+
def filter_stderr(filter, &block)
|
19
|
+
old_stderr = $stderr
|
20
|
+
$stderr = StringIO.new
|
21
|
+
begin
|
22
|
+
yield
|
23
|
+
ensure
|
24
|
+
what_they_tried_to_output = $stderr.string
|
25
|
+
$stderr = old_stderr
|
26
|
+
$stderr.print filter.call(what_they_tried_to_output)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
def filter_stdout(filter, &block)
|
30
|
+
old_stderr = $stdout
|
31
|
+
$stdout = StringIO.new
|
32
|
+
begin
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
what_they_tried_to_output = $stdout.string
|
36
|
+
$stdout = old_stderr
|
37
|
+
$stdout.print filter.call(what_they_tried_to_output)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# _____ _
|
42
|
+
# |_ _|__ ___| |_
|
43
|
+
# | |/ _ \/ __| __|
|
44
|
+
# | | __/\__ \ |_
|
45
|
+
# |_|\___||___/\__|
|
46
|
+
#
|
47
|
+
=begin test
|
48
|
+
require 'test/unit'
|
49
|
+
|
50
|
+
# Not sure whether it's better to duplicate for increased readability here or metaprogram for decreased duplication...
|
51
|
+
|
52
|
+
# Duplicate for increased readability:
|
53
|
+
def noisy_command
|
54
|
+
$stderr.puts "Some annoying error message"
|
55
|
+
$stderr.puts "Some error message that we actually care to see"
|
56
|
+
end
|
57
|
+
class TheTest < Test::Unit::TestCase
|
58
|
+
def setup
|
59
|
+
$stderr = StringIO.new
|
60
|
+
end
|
61
|
+
def test_simple_filter
|
62
|
+
filter_stderr(lambda{|input| ''}) do
|
63
|
+
noisy_command
|
64
|
+
end
|
65
|
+
assert_equal '', $stderr.string
|
66
|
+
end
|
67
|
+
def test_sub_filter
|
68
|
+
filter_stderr(Proc.new { |attempted_output|
|
69
|
+
attempted_output.sub(/^Some annoying error message\n/, '')
|
70
|
+
}
|
71
|
+
) do
|
72
|
+
noisy_command
|
73
|
+
end
|
74
|
+
assert_equal "Some error message that we actually care to see\n", $stderr.string
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Metaprogram for decreased duplication...
|
79
|
+
['stdout', 'stderr'].each do |stream_name|
|
80
|
+
eval <<-End, binding, __FILE__, __LINE__+1
|
81
|
+
def noisy_command_#{stream_name}
|
82
|
+
$#{stream_name}.puts "Some annoying error message"
|
83
|
+
$#{stream_name}.puts "Some error message that we actually care to see"
|
84
|
+
end
|
85
|
+
|
86
|
+
class TheTest#{stream_name} < Test::Unit::TestCase
|
87
|
+
def setup
|
88
|
+
$#{stream_name} = StringIO.new
|
89
|
+
end
|
90
|
+
def test_simple_filter
|
91
|
+
filter_#{stream_name}(lambda{|input| ''}) do
|
92
|
+
noisy_command_#{stream_name}
|
93
|
+
end
|
94
|
+
assert_equal '', $#{stream_name}.string
|
95
|
+
end
|
96
|
+
def test_sub_filter
|
97
|
+
filter_#{stream_name}(Proc.new { |attempted_output|
|
98
|
+
attempted_output.sub(/^Some annoying error message\n/, '')
|
99
|
+
}
|
100
|
+
) do
|
101
|
+
noisy_command_#{stream_name}
|
102
|
+
end
|
103
|
+
assert_equal "Some error message that we actually care to see\n", $#{stream_name}.string
|
104
|
+
end
|
105
|
+
end
|
106
|
+
End
|
107
|
+
end
|
108
|
+
=end
|
@@ -0,0 +1,178 @@
|
|
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
|
+
require 'rubygems'
|
10
|
+
require 'qualitysmith_extensions/object/ignore_access'
|
11
|
+
require 'qualitysmith_extensions/module/split'
|
12
|
+
require 'facets/core/module/by_name'
|
13
|
+
require 'facets/core/module/modspace'
|
14
|
+
|
15
|
+
class Module
|
16
|
+
alias_method :remove_const_before_was_added_to_Kernel, :remove_const
|
17
|
+
end
|
18
|
+
module Kernel
|
19
|
+
# This is similar to the built-in <tt>Module#remove_const</tt>, but it is accessible from all "levels" (because it is defined
|
20
|
+
# in +Kernel+) and can handle hierarchy.
|
21
|
+
#
|
22
|
+
# Makes it possible to write simply:
|
23
|
+
# remove_const(A::B::C.name)
|
24
|
+
# rather than having to think about which module the constant is actually defined in and calling +remove_const+ on that module.
|
25
|
+
#
|
26
|
+
# This is how you would otherwise have to do it:
|
27
|
+
# A::B.send(:remove_const, :C)
|
28
|
+
#
|
29
|
+
# +const_name+ must be an object that responds to +to_s+.
|
30
|
+
#
|
31
|
+
# +const_name+ must be a <i>fully qualified name</i>. For example, this will not work as expected:
|
32
|
+
#
|
33
|
+
# module Mod
|
34
|
+
# Foo = 'foo'
|
35
|
+
# remove_const(:Foo)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# because it will try to remove ::Foo instead of Mod::Foo. Fortunately, however, this will work as expected:
|
39
|
+
#
|
40
|
+
# module Mod
|
41
|
+
# Foo = 'foo'
|
42
|
+
# remove_const(Foo.name)
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# This method is partially inspired by Facets' Kernel#constant method, which provided a more user-friendly alternative to const_get.
|
46
|
+
#
|
47
|
+
def remove_const(const_name)
|
48
|
+
#require 'pp'
|
49
|
+
#puts "remove_const(#{const_name})"
|
50
|
+
raise ArgumentError unless const_name.respond_to?(:to_s)
|
51
|
+
nesting = const_name.to_s.split(/::/).map(&:to_sym)
|
52
|
+
if nesting.size > 1
|
53
|
+
parent_module = constant(nesting[0..-2].join('::')) # For example, would be A::B for A::B::C
|
54
|
+
const_to_remove = nesting[-1] # For example, would be :C for A::B::C
|
55
|
+
parent_module.ignore_access.remove_const_before_was_added_to_Kernel(const_to_remove)
|
56
|
+
else
|
57
|
+
ignore_access.remove_const_before_was_added_to_Kernel(const_name)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
#p Module.private_instance_methods.grep(/remove_const/) # Lists it
|
63
|
+
Module.send(:remove_method, :remove_const)
|
64
|
+
#p Module.instance_methods.grep(/remove_const/) # Does list it, because inherits *public* remove_const from Kernel
|
65
|
+
#p Module.private_instance_methods.grep(/remove_const/) # Does not list it, because it's no longer private
|
66
|
+
Module.send(:define_method, :remove_const, Kernel.method(:remove_const))
|
67
|
+
#p Module.private_instance_methods.grep(/remove_const/) # Lists it
|
68
|
+
|
69
|
+
# _____ _
|
70
|
+
# |_ _|__ ___| |_
|
71
|
+
# | |/ _ \/ __| __|
|
72
|
+
# | | __/\__ \ |_
|
73
|
+
# |_|\___||___/\__|
|
74
|
+
#
|
75
|
+
=begin test
|
76
|
+
require 'test/unit'
|
77
|
+
|
78
|
+
# Important regression test. This was failing at one point.
|
79
|
+
module A
|
80
|
+
B = nil
|
81
|
+
remove_const :B
|
82
|
+
end
|
83
|
+
|
84
|
+
# How it would be done *without* this extension:
|
85
|
+
module TestRemoveABC_TheOldWay
|
86
|
+
module A
|
87
|
+
module B
|
88
|
+
C = 'foo'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class TheTest < Test::Unit::TestCase
|
93
|
+
def test_1
|
94
|
+
assert_nothing_raised { A::B::C }
|
95
|
+
A::B.send(:remove_const, :C)
|
96
|
+
assert_raise(NameError) { A::B::C }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# How it would be done *with* this extension (all tests that follow):
|
102
|
+
|
103
|
+
module TestRemoveABC_CIsString
|
104
|
+
module A
|
105
|
+
module B
|
106
|
+
C = 'foo'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class TheTest < Test::Unit::TestCase
|
111
|
+
def test_1
|
112
|
+
assert_nothing_raised { A::B::C }
|
113
|
+
assert_raise(NoMethodError) { remove_const(A::B::C.name) } # Because C is a *string*, not a *module*
|
114
|
+
assert_nothing_raised { remove_const A::B.name + '::C' }
|
115
|
+
assert_raise(NameError) { A::B::C }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
module TestRemoveAB_UsingName
|
121
|
+
module A
|
122
|
+
module B
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class TheTest < Test::Unit::TestCase
|
127
|
+
def test_1
|
128
|
+
assert_nothing_raised { A::B }
|
129
|
+
remove_const(A::B.name)
|
130
|
+
assert_raise(NameError) { A::B }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
module TestRemoveAB_Symbol
|
136
|
+
module A
|
137
|
+
module B
|
138
|
+
Foo = :Foo
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
remove_const(:'A::B::Foo') # This tests that Module#remove_const was overriden as well.
|
143
|
+
# If we hadn't also overriden Module#remove_const, then this would have caused this error:
|
144
|
+
# in `remove_const': `A::B::Foo' is not allowed as a constant name (NameError)
|
145
|
+
|
146
|
+
class TheTest < Test::Unit::TestCase
|
147
|
+
def test_1
|
148
|
+
assert_nothing_raised { A::B }
|
149
|
+
|
150
|
+
assert_equal 'TestRemoveAB_Symbol::A', A.name
|
151
|
+
assert_raise(NameError) { remove_const(:'A::B') } # This doesn't work because A, when evaluated in this context,
|
152
|
+
# is TestRemoveAB_Symbol::TheTest::A, which is *not* defined.
|
153
|
+
|
154
|
+
remove_const(:'TestRemoveAB_Symbol::A::B')
|
155
|
+
assert_raise(NameError) { A::B }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
module TestRemoveAB_Symbol2
|
161
|
+
class TheTest < Test::Unit::TestCase
|
162
|
+
module A
|
163
|
+
module B
|
164
|
+
end
|
165
|
+
end
|
166
|
+
def test_1
|
167
|
+
assert_nothing_raised { A::B }
|
168
|
+
|
169
|
+
assert_equal 'TestRemoveAB_Symbol2::TheTest::A', A.name
|
170
|
+
remove_const(:'A::B') # Does work, because A is defined *within* TheTest this time.
|
171
|
+
assert_raise(NameError) { A::B }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
=end
|
177
|
+
|
178
|
+
|
@@ -0,0 +1,127 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: No.
|
6
|
+
# Developer notes::
|
7
|
+
# * Deprecated by qualitysmith_extensions/module/remove.rb
|
8
|
+
#++
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
require 'qualitysmith_extensions/object/ignore_access'
|
12
|
+
require 'qualitysmith_extensions/module/split'
|
13
|
+
require 'facets/core/module/by_name'
|
14
|
+
require 'facets/core/module/modspace'
|
15
|
+
|
16
|
+
module Kernel
|
17
|
+
# This is similar to +remove_const+, but it _only_ works for modules/classes.
|
18
|
+
#
|
19
|
+
# This is similar to the built-in <tt>Module#remove_module</tt>, but it is accessible from all "levels" (because it is defined
|
20
|
+
# in +Kernel+) and can handle hierarchy.
|
21
|
+
#
|
22
|
+
# Makes it possible to write simply:
|
23
|
+
# remove_module(A::B::C)
|
24
|
+
# rather than having to think about which module the constant is actually defined in and calling +remove_const+ on that module.
|
25
|
+
# This is how you would have to otherwise do it:
|
26
|
+
# A::B.send(:remove_const, :C)
|
27
|
+
#
|
28
|
+
# You can pass in either a constant or a symbol. Passing in a constant is preferred
|
29
|
+
#
|
30
|
+
# This method is partially inspired by Facets' Kernel#constant method, which provided a more user-friendly alternative to const_get.
|
31
|
+
#
|
32
|
+
def remove_module(const)
|
33
|
+
const = Module.by_name(const.to_s) if const.is_a?(Symbol)
|
34
|
+
if const.split.size > 1
|
35
|
+
parent_module = const.modspace # For example, would be A::B for A::B::C
|
36
|
+
const_to_remove = const.split.last # For example, would be :C for A::B::C
|
37
|
+
parent_module.ignore_access.remove_const(const_to_remove)
|
38
|
+
else
|
39
|
+
Object.ignore_access.remove_const(const.name)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# _____ _
|
45
|
+
# |_ _|__ ___| |_
|
46
|
+
# | |/ _ \/ __| __|
|
47
|
+
# | | __/\__ \ |_
|
48
|
+
# |_|\___||___/\__|
|
49
|
+
#
|
50
|
+
=begin test
|
51
|
+
require 'test/unit'
|
52
|
+
require 'qualitysmith_extensions/kernel/remove_const' # Test for compatibility. Just in case the remove_const_before_was_added_to_Kernel alias might have thrown something off.
|
53
|
+
|
54
|
+
# How it would be done *without* this extension:
|
55
|
+
module TestRemoveABC_TheOldWay
|
56
|
+
module A
|
57
|
+
module B
|
58
|
+
class C
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class TheTest < Test::Unit::TestCase
|
64
|
+
def test_1
|
65
|
+
assert_nothing_raised { A::B::C }
|
66
|
+
A::B.send(:remove_const, :C)
|
67
|
+
assert_raise(NameError) { A::B::C }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# How it would be done *with* this extension:
|
73
|
+
module TestRemoveABC
|
74
|
+
module A
|
75
|
+
module B
|
76
|
+
class C
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class TheTest < Test::Unit::TestCase
|
82
|
+
def test_1
|
83
|
+
assert_nothing_raised { A::B::C }
|
84
|
+
remove_module(A::B::C)
|
85
|
+
assert_raise(NameError) { A::B::C }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
module TestRemoveAB
|
91
|
+
module A
|
92
|
+
module B
|
93
|
+
module C
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class TheTest < Test::Unit::TestCase
|
99
|
+
def test_1
|
100
|
+
assert_nothing_raised { A::B }
|
101
|
+
remove_module(A::B)
|
102
|
+
assert_raise(NameError) { A::B }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
module TestRemoveAB_Symbol
|
108
|
+
module A
|
109
|
+
module B
|
110
|
+
module C
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class TheTest < Test::Unit::TestCase
|
116
|
+
def test_1
|
117
|
+
assert_nothing_raised { A::B }
|
118
|
+
assert_raise(NameError) { remove_module(:'A::B') } # This is why passing in the module itself is preferred.
|
119
|
+
remove_module(:'TestRemoveAB_Symbol::A::B')
|
120
|
+
assert_raise(NameError) { A::B }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
=end
|
126
|
+
|
127
|
+
|