qualitysmith_extensions 0.0.3

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.
Files changed (47) hide show
  1. data/Readme +72 -0
  2. data/lib/qualitysmith_extensions/all.rb +2 -0
  3. data/lib/qualitysmith_extensions/array/all.rb +2 -0
  4. data/lib/qualitysmith_extensions/array/average.rb +42 -0
  5. data/lib/qualitysmith_extensions/array/expand_ranges.rb +48 -0
  6. data/lib/qualitysmith_extensions/array/group_by.rb +112 -0
  7. data/lib/qualitysmith_extensions/array/sequence.rb +64 -0
  8. data/lib/qualitysmith_extensions/array/shell_escape.rb +34 -0
  9. data/lib/qualitysmith_extensions/array/to_a_recursive.rb +39 -0
  10. data/lib/qualitysmith_extensions/array/to_query_string.rb +94 -0
  11. data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
  12. data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
  13. data/lib/qualitysmith_extensions/console/command.rb +940 -0
  14. data/lib/qualitysmith_extensions/date/all.rb +2 -0
  15. data/lib/qualitysmith_extensions/date/deprecated.rb +38 -0
  16. data/lib/qualitysmith_extensions/date/iso8601.rb +29 -0
  17. data/lib/qualitysmith_extensions/date/month_ranges.rb +120 -0
  18. data/lib/qualitysmith_extensions/enumerable/enum.rb +72 -0
  19. data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +32 -0
  20. data/lib/qualitysmith_extensions/file_test/binary_file.rb +108 -0
  21. data/lib/qualitysmith_extensions/filter_output.rb +107 -0
  22. data/lib/qualitysmith_extensions/global_variable_set.rb +151 -0
  23. data/lib/qualitysmith_extensions/hash/all.rb +2 -0
  24. data/lib/qualitysmith_extensions/hash/to_date.rb +32 -0
  25. data/lib/qualitysmith_extensions/hash/to_query_string.rb +119 -0
  26. data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
  27. data/lib/qualitysmith_extensions/kernel/backtrace.rb +69 -0
  28. data/lib/qualitysmith_extensions/kernel/capture_output.rb +113 -0
  29. data/lib/qualitysmith_extensions/kernel/die.rb +34 -0
  30. data/lib/qualitysmith_extensions/kernel/require_all.rb +118 -0
  31. data/lib/qualitysmith_extensions/kernel/require_once.rb +16 -0
  32. data/lib/qualitysmith_extensions/month.rb +62 -0
  33. data/lib/qualitysmith_extensions/object/singleton.rb +95 -0
  34. data/lib/qualitysmith_extensions/simulate_input.rb +51 -0
  35. data/lib/qualitysmith_extensions/string/all.rb +2 -0
  36. data/lib/qualitysmith_extensions/string/digits_only.rb +25 -0
  37. data/lib/qualitysmith_extensions/string/md5.rb +27 -0
  38. data/lib/qualitysmith_extensions/string/shell_escape.rb +41 -0
  39. data/lib/qualitysmith_extensions/string/to_underscored_label.rb +35 -0
  40. data/lib/qualitysmith_extensions/test/assert_changed.rb +64 -0
  41. data/lib/qualitysmith_extensions/test/assert_exception.rb +63 -0
  42. data/lib/qualitysmith_extensions/test/assert_includes.rb +34 -0
  43. data/lib/qualitysmith_extensions/test/assert_user_error.rb +34 -0
  44. data/lib/qualitysmith_extensions/time/all.rb +2 -0
  45. data/lib/qualitysmith_extensions/time/deprecated.rb +29 -0
  46. data/test/all.rb +16 -0
  47. metadata +94 -0
@@ -0,0 +1,119 @@
1
+ # Author:: Anthony Kaufman, Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Yes.
5
+
6
+ autoload :CGI, 'cgi'
7
+ require 'rubygems'
8
+ require 'facets/core/kernel/require_local'
9
+ require_local '../array/to_query_string.rb'
10
+
11
+ class Hash
12
+
13
+ =begin rdoc
14
+ Converts into a string that can be used as the {query string}[http://en.wikipedia.org/wiki/Query_string] of a URL (for example, <tt>?key1=val1&key2=val2</tt>).
15
+
16
+ Example:
17
+ {
18
+ 'colors' => ['red', 'blue'],
19
+ 'username' => 'pineapple'
20
+ }.to_query_string('data')
21
+ ==> "data[username]=pineapple&data[colors][]=red&data[colors][]=blue"
22
+
23
+ The hash can be nested as deeply as you want and can also contain arrays.
24
+
25
+ <tt>key</tt> is the name of the key in params that will receive this hash when you load the page. So, for example, if you go to page with this query string (key = "name"): <tt>?name[first]=Fred&name[last]=Fredson</tt>, params will be have a key "name", like so: <tt>{"name"=>{"last"=>"Fredson", "first"=>"Fred"}}</tt>.
26
+
27
+ {
28
+ 'colors' => ['red', 'blue'],
29
+ 'username' => 'pineapple'
30
+ }.to_query_string('data')
31
+
32
+ is equivalent to just writing your hash like so:
33
+
34
+ {
35
+ 'data' => {
36
+ 'colors' => ['red', 'blue'],
37
+ 'username' => 'pineapple'
38
+ }
39
+ }.to_query_string()
40
+ =end
41
+ def to_query_string(key = '')
42
+ prefix = key.dup
43
+ elements = []
44
+
45
+ self.each_pair do |key, value|
46
+ key = CGI.escape key.to_s
47
+ key = prefix.length > 1 ? "#{prefix}[#{key}]" : key
48
+ if value.respond_to? :to_query_string
49
+ valuepre = value.dup
50
+ value = value.to_query_string(key)
51
+ #puts "#{key}#{valuepre.inspect} => #{value}"
52
+ elements << value
53
+ else
54
+ value = CGI.escape value.to_s
55
+ elements << key + '=' + value
56
+ end
57
+ end
58
+
59
+ elements.join('&')
60
+ end
61
+ end
62
+
63
+ # _____ _
64
+ # |_ _|__ ___| |_
65
+ # | |/ _ \/ __| __|
66
+ # | | __/\__ \ |_
67
+ # |_|\___||___/\__|
68
+ #
69
+ =begin test
70
+ class TheTest < Test::Unit::TestCase
71
+ def test_hash_to_query_string_nesting
72
+ data = {
73
+ 'foo' => 'bar',
74
+ 'names' => {
75
+ 'common' => 'smith',
76
+ 'uncommon' => {
77
+ :first => 'lance',
78
+ :last => 'wilheiminkauf'
79
+ }
80
+ }
81
+ }
82
+ assert_equal 'foo=bar&names[common]=smith&names[uncommon][first]=lance&names[uncommon][last]=wilheiminkauf', data.to_query_string
83
+ end
84
+ def test_hash_to_query_string_nesting_2
85
+ data = {
86
+ 'common' => 'smith',
87
+ 'uncommon' => [
88
+ 'frankenwatzel',
89
+ 'wilheiminkauf'
90
+ ]
91
+ }
92
+ assert_equal 'names[common]=smith&names[uncommon][]=frankenwatzel&names[uncommon][]=wilheiminkauf', data.to_query_string('names')
93
+ assert_equal( {'names' => data}.to_query_string(),
94
+ data.to_query_string('names') )
95
+ end
96
+
97
+ def test_hash_to_query_string_encoding
98
+ data = {'f&r' => 'a w$'}
99
+
100
+ assert_equal 'f%26r=a+w%24', data.to_query_string
101
+ end
102
+ end
103
+ =end
104
+
105
+ =begin examples
106
+ require 'irb/xmp'
107
+ xmp <<End
108
+ {
109
+ 'colors' => ['red', 'blue'],
110
+ 'username' => 'pineapple'
111
+ }.to_query_string('data')
112
+ {
113
+ 'data' => {
114
+ 'colors' => ['red', 'blue'],
115
+ 'username' => 'pineapple'
116
+ }
117
+ }.to_query_string()
118
+ End
119
+ =end
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + "/../kernel/require_all"
2
+ require_all File.dirname(__FILE__), :exclude_files => 'all.rb'
@@ -0,0 +1,69 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Not sure. This might not be necessary if caller() actually works reliably.
5
+
6
+ require "rubygems"
7
+ require "facet/string/lines"
8
+
9
+ module Kernel
10
+ # Equivalent to calling caller(0)
11
+ def backtrace
12
+ full_backtrace = caller(0)
13
+ return full_backtrace[1..-1] # We don't want this call to backtrace showing up in the backtrace, so skip top 1 frame.
14
+ end
15
+
16
+ # Returns a human-readable backtrace
17
+ def pretty_backtrace
18
+ "Backtrace:\n" +
19
+ backtrace[1..-1].map{|frame| "* " + frame}.join("\n")
20
+ end
21
+
22
+ # I thought I ran into some case where it didn't work to use caller(0)...which prompted me to do it this way (raise and rescue an exception)...but now I can't duplicate that problem, so I will deprecate this method.
23
+ def backtrace_using_exception
24
+ begin
25
+ raise "Where am I?"
26
+ rescue Exception => exception
27
+ full_backtrace = exception.backtrace
28
+ return full_backtrace[1..-1] # We don't want this call to backtrace showing up in the backtrace, so skip top 1 frame.
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+ # _____ _
35
+ # |_ _|__ ___| |_
36
+ # | |/ _ \/ __| __|
37
+ # | | __/\__ \ |_
38
+ # |_|\___||___/\__|
39
+ #
40
+ =begin test
41
+ class TheTest < Test::Unit::TestCase
42
+ def test_1_level
43
+ assert_match /^.*backtrace.rb:\d*:in `test_1_level'$/, backtrace[0]
44
+ assert_match /^.*testcase.rb:\d*:in `__send__'$/, backtrace[1]
45
+ end
46
+
47
+ def test_pretty_backtrace
48
+ assert_match /^Backtrace:$/, pretty_backtrace.lines[0]
49
+ assert_match /^.*backtrace.rb:\d*:in `test_pretty_backtrace'$/, pretty_backtrace.lines[1]
50
+ assert_match /^.*testcase.rb:\d*:in `__send__'$/, pretty_backtrace.lines[2]
51
+ end
52
+
53
+ def test_2_levels
54
+ assert_match /^.*backtrace.rb:\d*:in `a_method_that_returns_a_backtrace'$/, a_method_that_returns_a_backtrace[0]
55
+ assert_match /^.*backtrace.rb:\d*:in `test_2_levels'$/, a_method_that_returns_a_backtrace[1]
56
+ assert_match /^.*testcase.rb:\d*:in `__send__'$/, a_method_that_returns_a_backtrace[2]
57
+ end
58
+
59
+ def a_method_that_returns_a_backtrace
60
+ backtrace
61
+ end
62
+
63
+ def test_all_methods_of_getting_backtrace_are_equivalent
64
+ assert_equal backtrace_using_exception, backtrace
65
+ assert_equal backtrace_using_exception, caller(0)
66
+ end
67
+
68
+ end
69
+ =end
@@ -0,0 +1,113 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Yes
5
+
6
+ # :todo: Can we find a simpler way to do this based on facets' silence_stream?
7
+ #
8
+ # File lib/facets/core/kernel/silence_stream.rb, line 13
9
+ # def silence_stream(stream)
10
+ # old_stream = stream.dup
11
+ # stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null')
12
+ # stream.sync = true
13
+ # yield
14
+ # ensure
15
+ # stream.reopen(old_stream)
16
+ # end
17
+
18
+ require 'stringio'
19
+ require 'rubygems'
20
+ require 'facets/more/dictionary'
21
+
22
+ module Kernel
23
+
24
+ # Captures the output (stdout by default) that +block+ tries to generate and returns it as a string.
25
+ #
26
+ # output = capture_output($stderr) { noisy_command }
27
+ #
28
+ # output = capture_output([$stdout, $stderr]) do
29
+ # noisy_command
30
+ # end
31
+ #
32
+ # *Note*: If you specify more than one output stream, the entire results of each will be concatenated <i>in the order you listed them</i>, not necessarily in the order that you wrote _to_ those streams.
33
+ def capture_output(output_streams = $stdout, &block)
34
+ output_streams = [output_streams] unless output_streams.is_a? Array
35
+
36
+ saved_output_streams = Dictionary.new
37
+ output_streams.each do |output_stream|
38
+ case output_stream.object_id
39
+ when $stdout.object_id
40
+ saved_output_streams[:$stdout] = $stdout
41
+ $stdout = StringIO.new
42
+ when $stderr.object_id
43
+ saved_output_streams[:$stderr] = $stderr
44
+ $stderr = StringIO.new
45
+ end
46
+ end
47
+
48
+ what_they_tried_to_output = ''
49
+ begin
50
+ yield
51
+ rescue Exception
52
+ raise
53
+ ensure
54
+ saved_output_streams.each do |name, output_stream|
55
+ case name
56
+ when :$stdout
57
+ what_they_tried_to_output += $stdout.string
58
+ when :$stderr
59
+ what_they_tried_to_output += $stderr.string
60
+ end
61
+
62
+ # Restore the original output_stream that we saved.
63
+ case name
64
+ when :$stdout
65
+ $stdout = saved_output_streams[:$stdout]
66
+ when :$stderr
67
+ $stderr = saved_output_streams[:$stderr]
68
+ end
69
+ end
70
+ end
71
+ return what_they_tried_to_output
72
+ end
73
+
74
+ end
75
+
76
+ # _____ _
77
+ # |_ _|__ ___| |_
78
+ # | |/ _ \/ __| __|
79
+ # | | __/\__ \ |_
80
+ # |_|\___||___/\__|
81
+ #
82
+ =begin test
83
+ require 'test/unit'
84
+
85
+ def noisy_command
86
+ puts "Some lovely message"
87
+ $stderr.puts "Some lovely error message"
88
+ end
89
+ def noisy_command_with_error
90
+ puts "Some lovely message"
91
+ $stderr.puts "Some lovely error message"
92
+ raise 'an error'
93
+ end
94
+
95
+ class TheTest < Test::Unit::TestCase
96
+ def test_capture_all
97
+ assert_equal "Some lovely message\nSome lovely error message\n", capture_output([$stdout, $stderr]) { noisy_command }
98
+ end
99
+ def test_capture_all__different_order
100
+ # This is, I suppose a limitation of StingIO. This behavior may change in a future version if a workaround is found. (Creating a new IO subclass, +TimestampedStringIO+, that keeps a timestamp for every thing you add to it so that the results of two such objects can be merged to yield chronological output.)
101
+ assert_equal "Some lovely error message\nSome lovely message\n", capture_output([$stderr, $stdout]) { noisy_command }
102
+ end
103
+ def test_capture_stdout
104
+ assert_equal "Some lovely message\n", capture_output($stdout) { noisy_command }
105
+ end
106
+ def test_capture_stderr
107
+ assert_equal "Some lovely error message\n", capture_output($stderr) { noisy_command }
108
+ end
109
+ def test_when_an_error_is_raised_from_block
110
+ assert_raise(RuntimeError) { capture_output() { noisy_command_with_error } }
111
+ end
112
+ end
113
+ =end
@@ -0,0 +1,34 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Yes
5
+
6
+ module Kernel
7
+ def die(message)
8
+ $stderr.puts message
9
+ exit 1
10
+ end
11
+ end
12
+
13
+ # _____ _
14
+ # |_ _|__ ___| |_
15
+ # | |/ _ \/ __| __|
16
+ # | | __/\__ \ |_
17
+ # |_|\___||___/\__|
18
+ #
19
+ =begin test
20
+ require 'qualitysmith_extensions/kernel/capture_output'
21
+
22
+ class TheTest < Test::Unit::TestCase
23
+
24
+ def test_1
25
+ stderr = capture_output $stderr do
26
+ assert_raise(SystemExit) do
27
+ die "Aggh! I'm dying!"
28
+ end
29
+ end
30
+ assert_equal "Aggh! I'm dying!", stderr.chomp
31
+ end
32
+
33
+ end
34
+ =end
@@ -0,0 +1,118 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Yes
5
+
6
+ require 'rubygems'
7
+ require 'facets/more/filelist'
8
+
9
+ require 'facets/core/kernel/require_local'
10
+ require_local '../file/exact_match_regexp'
11
+
12
+ module Kernel
13
+
14
+ # Recursively <tt>require</tt>s all Ruby files in <tt>base_dir</tt> or any of its subdirectories.
15
+ # <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.
16
+ # <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.
17
+ #
18
+ # Note:
19
+ #
20
+ # Examples:
21
+ # require_all 'lib/', :exclude => [/ignore/, /bogus/] # will require 'lib/a.rb', 'lib/long/path/b.rb', but not 'lib/ignore/c.rb'
22
+ # require_all File.dirname(__FILE__), :exclude_files => ['blow_up_stuff.rb']
23
+ def require_all(base_dir, options = {})
24
+ base_dir += '/' unless base_dir[-1].chr == '/'
25
+ exclusions = nil
26
+ files = FileList[base_dir + "**/*.rb"]
27
+ files = files.exclude(*exclusions) if (exclusions = options.delete(:exclude))
28
+ files = files.exclude(*exclusions.map {|a| File.exact_match_regexp(a) }) if (exclusions = options.delete(:exclude_files))
29
+
30
+ files.each do |filename|
31
+ # puts "requiring #{filename}" if filename =~ /test/
32
+ require filename
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ # _____ _
39
+ # |_ _|__ ___| |_
40
+ # | |/ _ \/ __| __|
41
+ # | | __/\__ \ |_
42
+ # |_|\___||___/\__|
43
+ #
44
+ =begin test
45
+ require 'tmpdir'
46
+ require 'fileutils'
47
+
48
+ class TheTest < Test::Unit::TestCase
49
+ def setup
50
+ @main_subdir = 'require_all_test'
51
+ @base_dir = "#{Dir.tmpdir}/#{@main_subdir}"
52
+ FileUtils.mkdir @base_dir
53
+ FileUtils.mkdir_p @deep_dir = @base_dir + "/really/really/deep/subdir"
54
+ $loaded = Array.new(2)
55
+ end
56
+ def teardown
57
+ FileUtils.rm_rf @base_dir
58
+ end
59
+
60
+
61
+ def test_repeat_requires
62
+ $loaded[0] = 0
63
+ File.open("#{@base_dir}/moo.rb", "w") {|f| f.puts "$loaded[0] += 1"}
64
+ require_all File.dirname(@base_dir)
65
+ assert_equal [1, nil], $loaded
66
+
67
+ require "#{@base_dir}/moo.rb"
68
+ assert_equal [1, nil], $loaded
69
+
70
+ # Good! It refuses to load it again, even if we drop the ".rb" part!
71
+ require "#{@base_dir}/moo"
72
+ assert_equal [1, nil], $loaded
73
+
74
+ # But, we can still trick it!
75
+ $LOAD_PATH << @base_dir
76
+ require "moo"
77
+ assert_equal [2, nil], $loaded
78
+
79
+ load "moo.rb"
80
+ assert_equal [3, nil], $loaded
81
+ end
82
+
83
+ def test_deep_subdir
84
+ File.open("#{@base_dir}/flip.rb", "w") {|f| f.puts "$loaded[0] = true"}
85
+ File.open("#{@deep_dir}/flop.rb", "w") {|f| f.puts "$loaded[1] = true"}
86
+
87
+ require_all File.dirname(@base_dir)
88
+ assert_equal [true, true], $loaded
89
+ end
90
+
91
+ def test_exclude_pattern
92
+ File.open("#{@base_dir}/require_me.rb", "w") {|f| f.puts "$loaded[0] = true"}
93
+ File.open("#{@base_dir}/please_ignore_me.rb", "w") {|f| f.puts "$loaded[1] = true"}
94
+
95
+ require_all File.dirname(@base_dir), :exclude => [/ignore/]
96
+ assert_equal [true, nil], $loaded
97
+ end
98
+
99
+ def test_exclude_filename
100
+ File.open("#{@base_dir}/yes.rb", "w") {|f| f.puts "$loaded[0] = true"}
101
+ File.open("#{@base_dir}/all.rb", "w") {|f| f.puts "$loaded[1] = true"}
102
+
103
+ # :todo: Interesting how none of these patterns work. I would have expected them to. Is there a bug in FileList? Find out...
104
+ # /usr/lib/ruby/gems/1.8/gems/facets-1.8.51/lib/facets/more/filelist.rb
105
+ #require_all File.dirname(@base_dir), :exclude => ['all.rb']
106
+ #require_all File.dirname(@base_dir), :exclude => ['**/all']
107
+ #require_all File.dirname(@base_dir), :exclude => [/^all\.rb$/]
108
+ # This works, but it's too much to expect users to type out!:
109
+ #require_all File.dirname(@base_dir), :exclude => [/(\/|^)all\.rb$/]
110
+
111
+ # So...... I added an :exclude_files option so that people wouldn't have to!
112
+ require_all File.dirname(@base_dir), :exclude_files => ['all.rb']
113
+
114
+ assert_equal [true, nil], $loaded
115
+ end
116
+
117
+ end
118
+ =end
@@ -0,0 +1,16 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: No, not yet
5
+
6
+ require 'rubygems'
7
+
8
+ module Kernel
9
+ # 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.
10
+ def require_once(name)
11
+ raise NotImplementedError
12
+ # store expand_path(name) in an array ($required_files or something)
13
+ # only do the require if it wasn't already in the array
14
+ end
15
+ end
16
+
@@ -0,0 +1,62 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Not sure. Who really cares about Months anyway?
5
+
6
+ require "rubygems"
7
+ require "active_support"
8
+ require File.dirname(__FILE__) + "/date/all"
9
+
10
+ class Month
11
+ include Comparable
12
+ attr_reader :year, :month
13
+
14
+ def initialize(year, month)
15
+ @year = year
16
+ @month = month
17
+ end
18
+
19
+ def succ
20
+ (to_date >> 1).to_month
21
+ end
22
+
23
+ def to_date
24
+ Date.new(year, month)
25
+ end
26
+
27
+ def <=>(other)
28
+ #puts "#{self.inspect} <=> #{other.inspect}"
29
+ return self.to_date <=> other.to_date
30
+ end
31
+
32
+ def inspect
33
+ "#{@year}-#{@month}"
34
+ end
35
+ end
36
+
37
+
38
+ # _____ _
39
+ # |_ _|__ ___| |_
40
+ # | |/ _ \/ __| __|
41
+ # | | __/\__ \ |_
42
+ # |_|\___||___/\__|
43
+ #
44
+ =begin test
45
+ class TheTest < Test::Unit::TestCase
46
+ def test_months_range
47
+ range = Month.new(2006, 6)..Month.new(2006, 9)
48
+ assert_equal Range.new(Month.new(2006, 6), Month.new(2006, 9)), range
49
+
50
+ range = Date.new(2006, 6, 1).to_month..Date.new(2006, 9, 3).to_month
51
+ assert_equal Range.new(Month.new(2006, 6), Month.new(2006, 9)), range
52
+
53
+ assert_equal [
54
+ Month.new(2006, 6),
55
+ Month.new(2006, 7),
56
+ Month.new(2006, 8),
57
+ Month.new(2006, 9)
58
+ ],
59
+ range.to_a
60
+ end
61
+ end
62
+ =end
@@ -0,0 +1,95 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Yes
5
+ # Developer notes::
6
+ # * Method name too long? Imagine if we wanted to string multiple calls together.
7
+ # * Ideas:
8
+ # * single_send
9
+ # * singleton_send
10
+ # * singleton_call
11
+ # * singleton
12
+ # * singsend
13
+ # * extend_send
14
+ # * extend_call
15
+ # * create_and_send
16
+ # * create_and_call
17
+
18
+ class Object
19
+
20
+ # Creates a singleton method and then calls it.
21
+ #
22
+ # More specificaly, it +extend+s +self+ with the methods from +moduule+ and then sends the supplied +message+ and +args+ (if any).
23
+ #
24
+ # Advantages:
25
+ # * Keeps things object-oriented. Better than having global/class methods.
26
+ # ** (<tt>"whatever".single_send(MyColorizer, :colorize).single_send(SomeOtherClass, :another_class_method)</tt> instead of <tt>SomeOtherClass::another_class_method(MyColorizer::colorize("whatever"))</tt>)
27
+ # ** Method calls are _listed_ in the order in which they are _called_.
28
+ # * Still lets you keep your methods in a namespace.
29
+ # * Doesn't clutter up the base classes with methods that are only useful within a very small context. The methods are only added to the objects you specify. So you can "use" the base class <b>without cluttering up _all_ instances of the class with your methods</b>.
30
+ # * Useful for cases where creating a subclass wouldn't help because the methods you are calling would still return instances of the base class.
31
+ #
32
+ # Disadvantages:
33
+ # * You have to have/create a *module* for the functions you want to use.
34
+ # ** Can't just call .sigleton(self, :some_method) if some_method is defined in self.
35
+ # ** So what do we call the module containing the "singleton method"? String::MyColorizer? MyColorizer::String? MyStringColorizer?
36
+ #
37
+ # Examples:
38
+ # "whatever".singleton(MyColorizer, :colorize, :blue)
39
+ #
40
+ def singleton(moduule, message, *args)
41
+ self.extend(moduule)
42
+ self.send(message, *args)
43
+ end
44
+
45
+ def singleton_that_accepts_object(object, method_name, *args)
46
+ # #class << self
47
+ # #self.instance_eval do
48
+ # self.class.module_eval do
49
+ # define_method(:colorize2, object.class.instance_method(:colorize2))
50
+ # end
51
+ # # raises "TypeError: bind argument must be an instance of TheTest"
52
+
53
+ # object.class.instance_method(method_name).
54
+ # bind(self)
55
+ # # raises "TypeError: bind argument must be an instance of TheTest"
56
+
57
+ # self.class.extend(object.class)
58
+ # self.class.send(:include, object.class)
59
+ # # raises "TypeError: wrong argument type Class (expected Module)"
60
+ self.send(method_name, *args)
61
+ end
62
+
63
+ end
64
+
65
+ # _____ _
66
+ # |_ _|__ ___| |_
67
+ # | |/ _ \/ __| __|
68
+ # | | __/\__ \ |_
69
+ # |_|\___||___/\__|
70
+ #
71
+ =begin test
72
+ require 'test/unit'
73
+
74
+ module MyColorizer
75
+ def colorize(color = nil)
76
+ self + " (colorized in #{color})"
77
+ end
78
+ end
79
+
80
+ class TheTest < Test::Unit::TestCase
81
+ def test_1
82
+ assert_equal "whatever (colorized in )", "whatever".singleton(MyColorizer, :colorize)
83
+ assert_equal "whatever (colorized in blue)", "whatever".singleton(MyColorizer, :colorize, :blue)
84
+ end
85
+
86
+ # def test_2
87
+ # assert_equal "whatever (colorized in )", "whatever".singleton_that_accepts_object(self, :colorize2)
88
+ # assert_equal "whatever (colorized in blue)", "whatever".singleton_that_accepts_object(self, :colorize2, :blue)
89
+ # end
90
+ # def colorize2(color = nil)
91
+ # self + " (colorized2 in #{color})"
92
+ # end
93
+ end
94
+ =end
95
+
@@ -0,0 +1,51 @@
1
+ # Author:: Tyler Rick
2
+ # Copyright:: Copyright (c) 2007 QualitySmith, Inc.
3
+ # License:: Ruby License
4
+ # Submit to Facets?:: Yes
5
+ # Developer notes:
6
+ # * Move to kernel/?
7
+
8
+ require 'stringio'
9
+ require 'rubygems'
10
+
11
+ # Simulates a user typing in +input_string+ on the keyboard.
12
+ #
13
+ # Useful for testing console apps that are ordinarily (they prompt the user for input).
14
+ #
15
+ # output = simulate_inpute('foo') do
16
+ # input = $stdin.gets
17
+ # capture_output { do_stuff() }
18
+ # end
19
+ #
20
+ def simulate_input(input_string, &block)
21
+
22
+ original_stdin = $stdin
23
+ $stdin = StringIO.new(input_string, 'r')
24
+
25
+ begin
26
+ yield
27
+ rescue Exception
28
+ raise
29
+ ensure
30
+ $stdin = original_stdin
31
+ end
32
+ end
33
+
34
+
35
+ # _____ _
36
+ # |_ _|__ ___| |_
37
+ # | |/ _ \/ __| __|
38
+ # | | __/\__ \ |_
39
+ # |_|\___||___/\__|
40
+ #
41
+ =begin test
42
+ require 'test/unit'
43
+
44
+ class TheTest < Test::Unit::TestCase
45
+ def test_1
46
+ input_received = nil
47
+ simulate_input('foo') { input_received = $stdin.getc.chr }
48
+ assert_equal 'f', input_received
49
+ end
50
+ end
51
+ =end
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + "/../kernel/require_all"
2
+ require_all File.dirname(__FILE__), :exclude_files => 'all.rb'