qualitysmith_extensions 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme +72 -0
- data/lib/qualitysmith_extensions/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +42 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +48 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +112 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +64 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +34 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +39 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +94 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.rb +940 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +38 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +29 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +120 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +72 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +32 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +108 -0
- data/lib/qualitysmith_extensions/filter_output.rb +107 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +151 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +32 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +119 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +69 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +113 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +34 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +118 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +16 -0
- data/lib/qualitysmith_extensions/month.rb +62 -0
- data/lib/qualitysmith_extensions/object/singleton.rb +95 -0
- data/lib/qualitysmith_extensions/simulate_input.rb +51 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +25 -0
- data/lib/qualitysmith_extensions/string/md5.rb +27 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +41 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +35 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +64 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +63 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +34 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +34 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +29 -0
- data/test/all.rb +16 -0
- 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,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
|