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,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,4 @@
1
+ require 'rubygems'
2
+ # Alias for:
3
+ require 'qualitysmith_extensions/kernel/require_all'
4
+
@@ -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,6 @@
1
+ # Idea:
2
+ # Allow using hashes:
3
+ # alias_method :code_review => :view_commits
4
+ # instead of
5
+ # alias_method :code_review, :view_commits
6
+ # because I always forget which argument becomes the argument for which
@@ -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