qualitysmith_extensions 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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'