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,186 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes
|
6
|
+
#++
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require 'facets/more/filelist'
|
10
|
+
|
11
|
+
require 'facets/core/kernel/require_local'
|
12
|
+
require_local '../file/exact_match_regexp'
|
13
|
+
|
14
|
+
module Kernel
|
15
|
+
|
16
|
+
# <tt>require</tt>s all Ruby files specified by <tt>what</tt>, but not matching any of the exclude filters.
|
17
|
+
# * If <tt>what</tt> is a string, recursively <tt>require</tt>s all Ruby files in the directory named <tt>what</tt> or any of its subdirectories.
|
18
|
+
# * If <tt>what</tt> is a FileList, <tt>require</tt>s all Ruby files that match the <tt>what</tt> FileList.
|
19
|
+
#
|
20
|
+
# Options:
|
21
|
+
# <tt>:exclude</tt>: An array of regular expressions or glob patterns that will be passed to FileList#exclude. If you specify this option, a file will not be included if it matches *any* of these patterns.
|
22
|
+
# <tt>:exclude_files</tt>: An array of filenames to exclude. These will be matched exactly, so if you tell it to exclude 'bar.rb', 'foobar.rb' will _not_ be excluded.
|
23
|
+
#
|
24
|
+
# Examples:
|
25
|
+
# require_all 'lib/', :exclude => [/ignore/, /bogus/] # will require 'lib/a.rb', 'lib/long/path/b.rb', but not 'lib/ignore/c.rb'
|
26
|
+
# require_all File.dirname(__FILE__), :exclude_files => ['blow_up_stuff.rb']
|
27
|
+
def require_all(what, options = {})
|
28
|
+
files, exclusions = [nil]*2
|
29
|
+
|
30
|
+
case what
|
31
|
+
when String
|
32
|
+
base_dir = what
|
33
|
+
base_dir += '/' unless base_dir[-1].chr == '/'
|
34
|
+
files = FileList[base_dir + "**/*.rb"]
|
35
|
+
when FileList
|
36
|
+
files = what
|
37
|
+
else
|
38
|
+
raise ArgumentError.new("Expected a String or a FileList")
|
39
|
+
end
|
40
|
+
files = files.exclude(*exclusions) if (exclusions = options.delete(:exclude))
|
41
|
+
files = files.exclude(*exclusions.map {|a| File.exact_match_regexp(a) }) if (exclusions = options.delete(:exclude_files))
|
42
|
+
|
43
|
+
files.each do |filename|
|
44
|
+
# puts "requiring #{filename}" if filename =~ /test/
|
45
|
+
require filename
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# <tt>require</tt>s all Ruby files in +dir+ (relative to <tt>File.dirname(__FILE__)</tt>) or any of its subdirectories.
|
50
|
+
#
|
51
|
+
# This is just a shortcut for this:
|
52
|
+
# require_all File.join(File.dirname(__FILE__), dir)
|
53
|
+
#
|
54
|
+
# All of the +options+ available for +require_all+ are still available here.
|
55
|
+
#
|
56
|
+
def require_local_all(dir = './', options = {})
|
57
|
+
raise ArgumentError.new("dir must be a String") unless dir.is_a?(String)
|
58
|
+
local_dir = File.dirname( caller[0] )
|
59
|
+
require_all(
|
60
|
+
File.join(local_dir, dir),
|
61
|
+
options
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
# _____ _
|
68
|
+
# |_ _|__ ___| |_
|
69
|
+
# | |/ _ \/ __| __|
|
70
|
+
# | | __/\__ \ |_
|
71
|
+
# |_|\___||___/\__|
|
72
|
+
#
|
73
|
+
=begin test
|
74
|
+
require 'tmpdir'
|
75
|
+
require 'fileutils'
|
76
|
+
require 'English'
|
77
|
+
|
78
|
+
class TheTest < Test::Unit::TestCase
|
79
|
+
def setup
|
80
|
+
@base_dir = "#{Dir.tmpdir}/require_all_test"
|
81
|
+
@base_local_dir = File.dirname(__FILE__) # To allow testing of require_local_all. But tests should put everything in "#{@base_local_dir}/require_all_test" to avoid clutter or name conflicts with other files!
|
82
|
+
FileUtils.mkdir @base_dir
|
83
|
+
@deep_dir = "really/really/deep/subdir"
|
84
|
+
$loaded = []
|
85
|
+
|
86
|
+
end
|
87
|
+
def teardown
|
88
|
+
FileUtils.rm_rf @base_dir
|
89
|
+
FileUtils.rm_rf "#{@base_local_dir}/require_all_test"
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
def test_repeat_requires
|
94
|
+
create_ruby_file 'moo.rb'
|
95
|
+
|
96
|
+
require_all File.dirname(@base_dir)
|
97
|
+
assert_equal ['moo.rb'], $loaded
|
98
|
+
|
99
|
+
require "#{@base_dir}/moo.rb"
|
100
|
+
assert_equal ['moo.rb'], $loaded
|
101
|
+
|
102
|
+
# Good! It refuses to load it again, even if we drop the ".rb" part!
|
103
|
+
require "#{@base_dir}/moo"
|
104
|
+
assert_equal ['moo.rb'], $loaded
|
105
|
+
|
106
|
+
# But, we can still trick it!
|
107
|
+
$LOAD_PATH << @base_dir
|
108
|
+
require "moo"
|
109
|
+
assert_equal ['moo.rb', 'moo.rb'], $loaded
|
110
|
+
|
111
|
+
load "moo.rb"
|
112
|
+
assert_equal ['moo.rb', 'moo.rb', 'moo.rb'], $loaded
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_deep_subdir
|
116
|
+
create_ruby_file 'flip.rb'
|
117
|
+
create_ruby_file @deep_dir + "/flop.rb"
|
118
|
+
|
119
|
+
require_all File.dirname(@base_dir)
|
120
|
+
assert_equal ['flip.rb', @deep_dir + "/flop.rb"], $loaded
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_exclude_pattern
|
124
|
+
create_ruby_file 'require_me.rb'
|
125
|
+
create_ruby_file 'please_ignore_me.rb'
|
126
|
+
|
127
|
+
require_all File.dirname(@base_dir), :exclude => [/ignore/]
|
128
|
+
assert_equal ['require_me.rb'], $loaded
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_require_local_all
|
132
|
+
create_ruby_file 'require_all_test/lib/require_me.rb', @base_local_dir
|
133
|
+
create_ruby_file 'require_all_test/lib/please_ignore_me.rb', @base_local_dir
|
134
|
+
|
135
|
+
require_local_all 'require_all_test/lib', :exclude => [/ignore/]
|
136
|
+
assert_equal ['require_all_test/lib/require_me.rb'], $loaded
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_exclude_pattern_with_directory
|
140
|
+
create_ruby_file 'subdir/test/assert_even.rb'
|
141
|
+
create_ruby_file 'subdir/test/assert_odd.rb'
|
142
|
+
|
143
|
+
require_all File.dirname(@base_dir), :exclude => [/(^|\/)test/]
|
144
|
+
assert_equal [], $loaded
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_passing_a_FileList
|
148
|
+
create_ruby_file 'subdir/junk/pretty_much_useless.rb'
|
149
|
+
create_ruby_file 'subdir/not_junk/good_stuff.rb'
|
150
|
+
|
151
|
+
require_all FileList[File.dirname(@base_dir) + "/**/*.rb"], :exclude => [/(^|\/)junk/]
|
152
|
+
assert_equal ['subdir/not_junk/good_stuff.rb'], $loaded
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_exclude_filename
|
156
|
+
create_ruby_file 'yes.rb'
|
157
|
+
create_ruby_file 'all.rb'
|
158
|
+
|
159
|
+
# :todo: Interesting how none of these patterns work. I would have expected them to. Is there a bug in FileList? Find out...
|
160
|
+
# /usr/lib/ruby/gems/1.8/gems/facets-1.8.51/lib/facets/more/filelist.rb
|
161
|
+
#require_all File.dirname(@base_dir), :exclude => ['all.rb']
|
162
|
+
#require_all File.dirname(@base_dir), :exclude => ['**/all']
|
163
|
+
#require_all File.dirname(@base_dir), :exclude => [/^all\.rb$/]
|
164
|
+
# This works, but it's too much to expect users to type out!:
|
165
|
+
#require_all File.dirname(@base_dir), :exclude => [/(\/|^)all\.rb$/]
|
166
|
+
|
167
|
+
# So...... I added an :exclude_files option so that people wouldn't have to!
|
168
|
+
require_all File.dirname(@base_dir), :exclude_files => ['all.rb']
|
169
|
+
|
170
|
+
assert_equal ['yes.rb'], $loaded
|
171
|
+
end
|
172
|
+
|
173
|
+
#-------------------------------------------------------------------------------------------------------------------------------
|
174
|
+
# Helpers
|
175
|
+
|
176
|
+
def create_ruby_file(file_name, base_dir = @base_dir)
|
177
|
+
# use dirname instead?
|
178
|
+
if file_name =~ /(.*)\//
|
179
|
+
FileUtils.mkdir_p base_dir + '/' + $1
|
180
|
+
end
|
181
|
+
path = base_dir + '/' + file_name
|
182
|
+
File.open(path, "w") {|f| f.puts "$loaded << '#{file_name}'"}
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
=end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: No, not yet
|
6
|
+
#++
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
|
10
|
+
module Kernel
|
11
|
+
# Fixes bug in Ruby (1.8, at least -- not sure if 2.0 fixes it) where a file can be required twice if the path is spelled differently.
|
12
|
+
def require_once(name)
|
13
|
+
raise NotImplementedError
|
14
|
+
# store expand_path(name) in an array ($required_files or something)
|
15
|
+
# only do the require if it wasn't already in the array
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,52 @@
|
|
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
|
+
require 'rubygems'
|
11
|
+
|
12
|
+
# Simulates a user typing in +input_string+ on the keyboard.
|
13
|
+
#
|
14
|
+
# Useful for testing console apps that are ordinarily (they prompt the user for input).
|
15
|
+
#
|
16
|
+
# output = simulate_inpute('foo') do
|
17
|
+
# input = $stdin.gets
|
18
|
+
# capture_output { do_stuff() }
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
def simulate_input(input_string, &block)
|
22
|
+
|
23
|
+
original_stdin = $stdin
|
24
|
+
$stdin = StringIO.new(input_string, 'r')
|
25
|
+
|
26
|
+
begin
|
27
|
+
yield
|
28
|
+
rescue Exception
|
29
|
+
raise
|
30
|
+
ensure
|
31
|
+
$stdin = original_stdin
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
# _____ _
|
37
|
+
# |_ _|__ ___| |_
|
38
|
+
# | |/ _ \/ __| __|
|
39
|
+
# | | __/\__ \ |_
|
40
|
+
# |_|\___||___/\__|
|
41
|
+
#
|
42
|
+
=begin test
|
43
|
+
require 'test/unit'
|
44
|
+
|
45
|
+
class TheTest < Test::Unit::TestCase
|
46
|
+
def test_1
|
47
|
+
input_received = nil
|
48
|
+
simulate_input('foo') { input_received = $stdin.getc.chr }
|
49
|
+
assert_equal 'f', input_received
|
50
|
+
end
|
51
|
+
end
|
52
|
+
=end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes!
|
6
|
+
#++
|
7
|
+
|
8
|
+
module Kernel
|
9
|
+
# Calling <tt>Kernel#trap()</tt> by itself will _replace_ any previously registered handler code.
|
10
|
+
# <tt>Kernel#trap_chain()</tt>, on the other hand, will _add_ the block you supply to the existing "list" of registered handler blocks.
|
11
|
+
# Similar to the way <tt>Kernel#at_exit()</tt> works, <tt>Kernel#trap_chain()</tt> will _prepend_ the given +block+ to the call chain for the given +signal_name+.
|
12
|
+
# When the signal occurs, your block will be executed first and then the previously registered handler will be invoked. This can be called repeatedly to create a "chain" of handlers.
|
13
|
+
def trap_chain(signal_name, *args, &block)
|
14
|
+
previous_interrupt_handler = trap(signal_name, *args) {}
|
15
|
+
trap(signal_name, *args) do
|
16
|
+
block.call
|
17
|
+
previous_interrupt_handler.call unless previous_interrupt_handler == "DEFAULT"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# _____ _
|
23
|
+
# |_ _|__ ___| |_
|
24
|
+
# | |/ _ \/ __| __|
|
25
|
+
# | | __/\__ \ |_
|
26
|
+
# |_|\___||___/\__|
|
27
|
+
#
|
28
|
+
=begin test
|
29
|
+
require 'rubygems'
|
30
|
+
require 'qualitysmith_extensions/kernel/capture_output'
|
31
|
+
require 'fileutils'
|
32
|
+
|
33
|
+
class TheTest < Test::Unit::TestCase
|
34
|
+
def setup
|
35
|
+
FileUtils.touch('trap_chain_test_output')
|
36
|
+
end
|
37
|
+
def teardown
|
38
|
+
FileUtils.remove_entry_secure 'trap_chain_test_output'
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_1
|
42
|
+
output = capture_output do # For some reason, this wasn't capturing the output from the child process when I did plain puts, so I changed it to write to a file instead...
|
43
|
+
|
44
|
+
pid = fork do
|
45
|
+
trap_chain("INT") { File.open('trap_chain_test_output', 'a') {|file| file.puts "Handler 1" } }
|
46
|
+
trap_chain("INT") { File.open('trap_chain_test_output', 'a') {|file| file.puts "Handler 2"; file.puts "Exiting..."; }; exit }
|
47
|
+
trap_chain("INT") { File.open('trap_chain_test_output', 'a') {|file| file.puts "Handler 3" } }
|
48
|
+
puts 'Hello world'
|
49
|
+
sleep 5
|
50
|
+
end
|
51
|
+
Process.kill "INT", pid
|
52
|
+
Process.wait
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
assert_equal "Handler 3\nHandler 2\nExiting...\n", File.read('trap_chain_test_output')
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
=end
|
61
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes
|
6
|
+
# Developer notes::
|
7
|
+
# Changes::
|
8
|
+
#++
|
9
|
+
|
10
|
+
|
11
|
+
module Kernel
|
12
|
+
def windows_platform?
|
13
|
+
RUBY_PLATFORM =~ /mswin32/
|
14
|
+
|
15
|
+
# What about mingw32 or cygwin32?
|
16
|
+
#RUBY_PLATFORM =~ /(win|w)32$/
|
17
|
+
|
18
|
+
# What about 64-bit Windows?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
# _____ _
|
29
|
+
# |_ _|__ ___| |_
|
30
|
+
# | |/ _ \/ __| __|
|
31
|
+
# | | __/\__ \ |_
|
32
|
+
# |_|\___||___/\__|
|
33
|
+
#
|
34
|
+
=begin test
|
35
|
+
require 'test/unit'
|
36
|
+
|
37
|
+
class TheTest < Test::Unit::TestCase
|
38
|
+
def test_1
|
39
|
+
# Impossible to test, unless your platform is Windows.
|
40
|
+
assert true
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
=end
|
45
|
+
|
46
|
+
|
@@ -0,0 +1,165 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 the Rails people; QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Developer notes::
|
7
|
+
# Changes::
|
8
|
+
#++
|
9
|
+
|
10
|
+
require 'rubygems'
|
11
|
+
gem 'facets'
|
12
|
+
#require 'facets/core/module/alias_method_chain' # Doesn't support blocks or I'd use it.
|
13
|
+
require 'facets/core/kernel/singleton_class'
|
14
|
+
|
15
|
+
|
16
|
+
# /usr/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/core_ext/module/aliasing.rb
|
17
|
+
class Module
|
18
|
+
def alias_method_chain(target, feature)
|
19
|
+
# Strip out punctuation on predicates or bang methods since
|
20
|
+
# e.g. target?_without_feature is not a valid method name.
|
21
|
+
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
|
22
|
+
yield(aliased_target, punctuation) if block_given?
|
23
|
+
alias_method "#{aliased_target}_without_#{feature}#{punctuation}", target
|
24
|
+
alias_method target, "#{aliased_target}_with_#{feature}#{punctuation}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
# end /usr/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/core_ext/module/aliasing.rb
|
28
|
+
|
29
|
+
class Module
|
30
|
+
|
31
|
+
def alias_method_chain_with_prevent_repeat_aliasing(target, feature, &block)
|
32
|
+
# Strip out punctuation on predicates or bang methods since
|
33
|
+
# e.g. target?_without_feature is not a valid method name.
|
34
|
+
|
35
|
+
aliased_target, punctuation = target.to_s.sub(/([?!])$/, ''), $1
|
36
|
+
target_without_feature = "#{aliased_target}_without_#{feature}#{punctuation}"
|
37
|
+
|
38
|
+
#puts "#{target} is #{method_defined?(target)}"
|
39
|
+
alias_method_chain_without_prevent_repeat_aliasing(target, feature, &block) unless method_defined?(target_without_feature)
|
40
|
+
end
|
41
|
+
alias_method_chain :alias_method_chain, :prevent_repeat_aliasing
|
42
|
+
|
43
|
+
# If you pass <tt>:create_target => true</tt> as one of the +options+:
|
44
|
+
# * Guarantees that <tt>alias_method_chain target, feature</tt> will work even if the target method has not been defined yet.
|
45
|
+
# If the target method doesn't exist yet, an empty (no-op) target method will be created.
|
46
|
+
# * This could come in handy for callback methods (method_added, method_missing, etc.), for instane, when you don't know if that
|
47
|
+
# particular callback method has been defined or not.
|
48
|
+
# * You want your alias_method_chain to wrap the existing method if there *is* an existing method, but to <b>not break</b> in
|
49
|
+
# the case that the method _doesn't_ exist.
|
50
|
+
def alias_method_chain_with_target_need_not_exist(target, feature, options = {}, &block)
|
51
|
+
create_target = options.delete(:create_target)
|
52
|
+
|
53
|
+
if create_target && true #!self.methods.include?(target)
|
54
|
+
self.send :define_method, target do |*args|
|
55
|
+
# Intentionally empty
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
alias_method_chain_without_target_need_not_exist(target, feature, &block)
|
60
|
+
end
|
61
|
+
alias_method_chain :alias_method_chain, :target_need_not_exist
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
=begin test
|
67
|
+
require 'test/unit'
|
68
|
+
|
69
|
+
class Test_alias_method_chain_basic < Test::Unit::TestCase
|
70
|
+
|
71
|
+
class X
|
72
|
+
def foo?
|
73
|
+
'foo?'
|
74
|
+
end
|
75
|
+
def foo_with_feature?
|
76
|
+
foo_without_feature? + '_with_feature'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_question_mark
|
81
|
+
name, punctuation = nil, nil
|
82
|
+
X.instance_eval do
|
83
|
+
alias_method_chain :foo?, :feature do |a, b|
|
84
|
+
name, punctuation = a, b
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
assert_equal 'foo?_with_feature', X.new.foo?
|
89
|
+
assert_equal 'foo', name
|
90
|
+
assert_equal '?', punctuation
|
91
|
+
end
|
92
|
+
|
93
|
+
class Y
|
94
|
+
def foo!
|
95
|
+
'foo!'
|
96
|
+
end
|
97
|
+
def foo_with_feature!
|
98
|
+
foo_without_feature! + '_with_feature'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_exclamation_mark
|
103
|
+
name, punctuation = nil, nil
|
104
|
+
Y.instance_eval do
|
105
|
+
alias_method_chain :foo!, :feature do |a, b|
|
106
|
+
name, punctuation = a, b
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
assert_equal 'foo!_with_feature', Y.new.foo!
|
111
|
+
assert_equal 'foo', name
|
112
|
+
assert_equal '!', punctuation
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
class Test_alias_method_chain_with_prevent_repeat_aliasing < Test::Unit::TestCase
|
118
|
+
|
119
|
+
class X
|
120
|
+
def foo
|
121
|
+
'foo'
|
122
|
+
end
|
123
|
+
def foo_with_feature
|
124
|
+
foo_without_feature + '_with_feature'
|
125
|
+
end
|
126
|
+
alias_method_chain :foo, :feature
|
127
|
+
alias_method_chain :foo, :feature # We want to test that this won't cause an infinite recursion (stack overflow).
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_1
|
131
|
+
assert_equal 'foo_with_feature', X.new.foo
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
class Test_alias_method_chain_with_target_need_not_exist < Test::Unit::TestCase
|
138
|
+
|
139
|
+
# Let's assume that we are *re*-opening X here, and at this point we *don't know* if it has a foo method or not.
|
140
|
+
# Also, we *don't want to care*. We just want to add to the chain if the method exists, or *create* the chain
|
141
|
+
# if it does not yet.
|
142
|
+
class X
|
143
|
+
def foo_with_feature
|
144
|
+
# *Don't* do this if you're using :create_target => true:
|
145
|
+
# foo_without_feature + '_with_feature'
|
146
|
+
# If you're using :create_target => true, then you are pretty much saying "I don't know anything about thhe target method".
|
147
|
+
# Yet the previous statement shows that you expect it to return a String. You can't do that. You can't pretend to know
|
148
|
+
# anything about it's return value. It will always be nil if alias_method_chain created an empty method for you.
|
149
|
+
# But, it may be something else if it already existed and alias_method_chain did *not* create an empty method for you.
|
150
|
+
|
151
|
+
# The safest thing to do is to just call it and pay not attention to its return value. (Or at least *consider* the
|
152
|
+
# possibility that it may be nil.)
|
153
|
+
|
154
|
+
foo_without_feature
|
155
|
+
'feature was successfully added'
|
156
|
+
end
|
157
|
+
alias_method_chain :foo, :feature, :create_target => true
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_1
|
161
|
+
assert_equal 'feature was successfully added', X.new.foo
|
162
|
+
assert_equal 'feature was successfully added', X.new.foo { 'test that it works with a block' }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
=end
|