AvantiConveniences 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/AvantiConveniences.gemspec +42 -0
- data/History.txt +32 -0
- data/Manifest.txt +26 -0
- data/README.txt +80 -0
- data/Rakefile +77 -0
- data/lib/arg_checks.rb +79 -0
- data/lib/array_extensions.rb +5 -0
- data/lib/avanti_conveniences.rb +13 -0
- data/lib/die.rb +5 -0
- data/lib/float_extensions.rb +3 -0
- data/lib/hash_extensions.rb +22 -0
- data/lib/string_extensions.rb +25 -0
- data/lib/text_formatter.rb +83 -0
- data/lib/time_extensions.rb +6 -0
- data/lib/uri_extensions.rb +23 -0
- data/test/test_arg_checks.rb +113 -0
- data/test/test_array_extensions.rb +36 -0
- data/test/test_avanti_conveniences.rb +9 -0
- data/test/test_die.rb +22 -0
- data/test/test_float_extensions.rb +17 -0
- data/test/test_hash_extensions.rb +23 -0
- data/test/test_string_extensions.rb +57 -0
- data/test/test_text_formatter.rb +81 -0
- data/test/test_time_extensions.rb +23 -0
- data/test/test_uri_extensions.rb +14 -0
- metadata +131 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{AvantiConveniences}
|
5
|
+
s.version = "1.0.4"
|
6
|
+
|
7
|
+
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
+
s.authors = ["Jamie Flournoy"]
|
10
|
+
s.date = %q{2009-03-20}
|
11
|
+
s.description = %q{AvantiConveniences is a set of convenience code for Ruby on Rails applications.}
|
12
|
+
s.email = ["jamie@pervasivecode.com"]
|
13
|
+
s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
|
14
|
+
s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "lib/arg_checks.rb", "lib/avanti_conveniences.rb", "lib/hash_extensions.rb", "lib/string_extensions.rb", "lib/text_formatter.rb", "lib/uri_extensions.rb", "test/test_arg_checks.rb", "test/test_avanti_conveniences.rb", "test/test_hash_extensions.rb", "test/test_string_extensions.rb", "test/test_text_formatter.rb", "test/test_uri_extensions.rb"]
|
15
|
+
s.has_rdoc = true
|
16
|
+
s.homepage = %q{http://www.pervasivecode.com/blog/avanticonveniences/}
|
17
|
+
s.rdoc_options = ["--main", "README.txt"]
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubyforge_project = %q{avanticonveniences}
|
20
|
+
s.rubygems_version = %q{1.3.1}
|
21
|
+
s.summary = %q{AvantiConveniences is a set of convenience code for Ruby on Rails applications.}
|
22
|
+
s.test_files = ["test/test_arg_checks.rb", "test/test_avanti_conveniences.rb", "test/test_hash_extensions.rb", "test/test_string_extensions.rb", "test/test_text_formatter.rb", "test/test_uri_extensions.rb"]
|
23
|
+
|
24
|
+
if s.respond_to? :specification_version then
|
25
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
26
|
+
s.specification_version = 2
|
27
|
+
|
28
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
29
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 1.2.6"])
|
30
|
+
s.add_runtime_dependency(%q<text-hyphen>, [">= 1.0.0"])
|
31
|
+
s.add_development_dependency(%q<hoe>, [">= 1.11.0"])
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<activesupport>, [">= 1.2.6"])
|
34
|
+
s.add_dependency(%q<text-hyphen>, [">= 1.0.0"])
|
35
|
+
s.add_dependency(%q<hoe>, [">= 1.11.0"])
|
36
|
+
end
|
37
|
+
else
|
38
|
+
s.add_dependency(%q<activesupport>, [">= 1.2.6"])
|
39
|
+
s.add_dependency(%q<text-hyphen>, [">= 1.0.0"])
|
40
|
+
s.add_dependency(%q<hoe>, [">= 1.11.0"])
|
41
|
+
end
|
42
|
+
end
|
data/History.txt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
=== 1.0.6 / 2009-12-22
|
2
|
+
|
3
|
+
* Added Array#average, Die.roll, Float::INFINITY, Time#at_midnight
|
4
|
+
* Updated to use Hoe 2.0.
|
5
|
+
|
6
|
+
=== 1.0.5 / 2009-07-27
|
7
|
+
|
8
|
+
* Added Hash#map_keys, Hash#map_values, and Hash#map_pairs.
|
9
|
+
|
10
|
+
=== 1.0.4 / 2009-03-20
|
11
|
+
|
12
|
+
* Fixed the 'rcov' Rake task so it worked with the latest Hoe.
|
13
|
+
* Added a bit of documentation that was missing.
|
14
|
+
|
15
|
+
=== 1.0.3 / 2008-11-11
|
16
|
+
|
17
|
+
* Bug fix for a hang in TextFormatter.hyphenate_word, when given a wprd that contains multiple hyphens.
|
18
|
+
|
19
|
+
=== 1.0.2 / 2008-09-29
|
20
|
+
|
21
|
+
* Made TextFormatter.split_long_words take a fourth optional argument to control insertion of newlines in split text.
|
22
|
+
|
23
|
+
=== 1.0.1 / 2008-08-30
|
24
|
+
|
25
|
+
* Changed the output of ArgChecks.arg_type so that it includes the to_s representation of the object itself in the exception message.
|
26
|
+
* Added ArgChecks.arg_responds_to.
|
27
|
+
|
28
|
+
=== 1.0.0 / 2008-08-04
|
29
|
+
|
30
|
+
* First release.
|
31
|
+
|
32
|
+
* Birthday!
|
data/Manifest.txt
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
AvantiConveniences.gemspec
|
2
|
+
History.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
Rakefile
|
6
|
+
lib/arg_checks.rb
|
7
|
+
lib/array_extensions.rb
|
8
|
+
lib/avanti_conveniences.rb
|
9
|
+
lib/die.rb
|
10
|
+
lib/float_extensions.rb
|
11
|
+
lib/hash_extensions.rb
|
12
|
+
lib/string_extensions.rb
|
13
|
+
lib/text_formatter.rb
|
14
|
+
lib/time_extensions.rb
|
15
|
+
lib/uri_extensions.rb
|
16
|
+
test/test_arg_checks.rb
|
17
|
+
test/test_array_extensions.rb
|
18
|
+
test/test_avanti_conveniences.rb
|
19
|
+
test/test_die.rb
|
20
|
+
test/test_float_extensions.rb
|
21
|
+
test/test_hash_extensions.rb
|
22
|
+
test/test_string_extensions.rb
|
23
|
+
test/test_text_formatter.rb
|
24
|
+
test/test_time_extensions.rb
|
25
|
+
test/test_uri_extensions.rb
|
26
|
+
|
data/README.txt
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
= AvantiConveniences
|
2
|
+
|
3
|
+
http://www.pervasivecode.com/blog/avanticonveniences/
|
4
|
+
Author: Jamie Flournoy (jamie@pervasivecode.com)
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
AvantiConveniences is a set of convenience code for Ruby on Rails applications.
|
9
|
+
|
10
|
+
== FEATURES/PROBLEMS:
|
11
|
+
|
12
|
+
ArgChecks helps you implement simple sanity-checking of arguments, like
|
13
|
+
permanent assertions or a poor man's Design by Contract facility, so you can
|
14
|
+
write code that will Fail Fast (see http://c2.com/cgi/wiki?FailFast).
|
15
|
+
|
16
|
+
ArrayExtensions adds Array#average.
|
17
|
+
|
18
|
+
Die adds Die.roll which is semantic sugar around rand(n).
|
19
|
+
|
20
|
+
FloatExtensions adds Float::INFINITY, which is semantic sugar for people
|
21
|
+
who don't want to see '1.0 / 0' in your code.
|
22
|
+
|
23
|
+
HashExtensions adds a few methods that help you easily replace all the keys
|
24
|
+
and/or values at once.
|
25
|
+
|
26
|
+
StringExtensions provides String quoting (not escaping) with single quotes,
|
27
|
+
double quotes, or a caller-specified quoting character, and a String#dehumanize
|
28
|
+
method to do the reverse of the String#humanize method provided by ActiveSupport.
|
29
|
+
|
30
|
+
TextFormatter provides methods for hyphenating words for word-wrapping.
|
31
|
+
|
32
|
+
TimeExtensions provides Time#at_midnight, which is useful if you want to work
|
33
|
+
with a lot of timestamps that need to be bucketed by day.
|
34
|
+
|
35
|
+
URIExtensions provides URI::Generic#query_from_hash, which will create a URI
|
36
|
+
query string from a Hash.
|
37
|
+
|
38
|
+
== SYNOPSIS:
|
39
|
+
|
40
|
+
See individual classes for details. All of them are single method invocations
|
41
|
+
that are very simple to use. For additional examples look in the test/
|
42
|
+
directory.
|
43
|
+
|
44
|
+
== REQUIREMENTS:
|
45
|
+
|
46
|
+
Ruby 1.8.5 (might work with earlier versions), ActiveSupport 1.2.6, Text-Hyphen
|
47
|
+
1.0.0, and Hoe 1.7.0.
|
48
|
+
|
49
|
+
== INSTALL:
|
50
|
+
|
51
|
+
If you haven't done this before:
|
52
|
+
gem sources -a http://gems.github.com
|
53
|
+
|
54
|
+
Then:
|
55
|
+
sudo gem install JamieFlournoy-AvantiConveniences
|
56
|
+
|
57
|
+
== LICENSE:
|
58
|
+
|
59
|
+
(The MIT License)
|
60
|
+
|
61
|
+
Copyright (c) 2008 Pervasive Code
|
62
|
+
|
63
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
64
|
+
a copy of this software and associated documentation files (the
|
65
|
+
'Software'), to deal in the Software without restriction, including
|
66
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
67
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
68
|
+
permit persons to whom the Software is furnished to do so, subject to
|
69
|
+
the following conditions:
|
70
|
+
|
71
|
+
The above copyright notice and this permission notice shall be
|
72
|
+
included in all copies or substantial portions of the Software.
|
73
|
+
|
74
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
75
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
76
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
77
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
78
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
79
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
80
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
# Hoe::plugin :gemcutter
|
7
|
+
|
8
|
+
hoe = Hoe.spec 'AvantiConveniences' do
|
9
|
+
developer('Jamie Flournoy', 'jamie@pervasivecode.com')
|
10
|
+
extra_deps << ['activesupport', '>= 1.2.6']
|
11
|
+
extra_deps << ['text-hyphen', '>= 1.0.0']
|
12
|
+
extra_dev_deps << ['thoughtbot-shoulda', '>= 2.10.1']
|
13
|
+
end
|
14
|
+
|
15
|
+
task :gemspec do
|
16
|
+
File.open("#{hoe.name}.gemspec", "w") {|f| f << hoe.spec.to_ruby }
|
17
|
+
end
|
18
|
+
task :package => :gemspec
|
19
|
+
|
20
|
+
|
21
|
+
# The rcov task in this file worked until Hoe was updated; this code keeps the old behavior
|
22
|
+
# and disables Hoe's rcov task.
|
23
|
+
Rake::TaskManager.class_eval do
|
24
|
+
def remove_task(task_name)
|
25
|
+
@tasks.delete(task_name.to_s)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def remove_task(task_name)
|
29
|
+
Rake.application.remove_task(task_name)
|
30
|
+
end
|
31
|
+
remove_task 'rcov'
|
32
|
+
|
33
|
+
|
34
|
+
task :rcov do
|
35
|
+
sh 'rcov test/test_*.rb'
|
36
|
+
end
|
37
|
+
task :clean_rcov do
|
38
|
+
sh 'rm -rf ./coverage/*'
|
39
|
+
end
|
40
|
+
task :clean => [:clean_rcov]
|
41
|
+
|
42
|
+
|
43
|
+
# vim: syntax=Ruby
|
44
|
+
|
45
|
+
|
46
|
+
# stats
|
47
|
+
begin
|
48
|
+
gem 'rails'
|
49
|
+
require 'code_statistics'
|
50
|
+
namespace :spec do
|
51
|
+
desc "Use Rails's rake:stats task for a gem"
|
52
|
+
task :statsetup do
|
53
|
+
class CodeStatistics
|
54
|
+
def calculate_statistics
|
55
|
+
@pairs.inject({}) do |stats, pair|
|
56
|
+
if 3 == pair.size
|
57
|
+
stats[pair.first] = calculate_directory_statistics(pair[1], pair[2]); stats
|
58
|
+
else
|
59
|
+
stats[pair.first] = calculate_directory_statistics(pair.last); stats
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
::STATS_DIRECTORIES = [['Libraries', 'lib', /\.(sql|rhtml|erb|rb|yml)$/],
|
65
|
+
['Tests', 'test', /\.(sql|rhtml|erb|rb|yml)$/]]
|
66
|
+
::CodeStatistics::TEST_TYPES << "Tests"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
desc "Report code statistics (KLOCs, etc) from the application"
|
70
|
+
task :stats => "spec:statsetup" do
|
71
|
+
CodeStatistics.new(*STATS_DIRECTORIES).to_s
|
72
|
+
end
|
73
|
+
rescue Gem::LoadError => le
|
74
|
+
task :stats do
|
75
|
+
raise RuntimeError, "'rails' gem not found - you must install it in order to use this task.\n"
|
76
|
+
end
|
77
|
+
end
|
data/lib/arg_checks.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Include this module in your classes that need sanity checking of method arguments.
|
2
|
+
# If any of these checks is not satisfied, it will raise an ArgumentError with a
|
3
|
+
# detailed message about what went wrong.
|
4
|
+
module ArgChecks
|
5
|
+
# Require that all arguments be of the specified class, or one of its subclasses (uses is_a?).
|
6
|
+
# Consider using arg_responds_to? or respond_to? instead, to make your API more flexible.
|
7
|
+
def arg_type(klass, *args)
|
8
|
+
raise ArgumentError, "First argument must be a class. Got #{klass.to_s}" unless klass.is_a? Class
|
9
|
+
args.each{|obj| raise ArgumentError, "Wrong type for argument '#{obj}' (should be #{klass})" unless obj.is_a? klass }
|
10
|
+
end
|
11
|
+
|
12
|
+
# Require that all arguments respond_to? the specified method.
|
13
|
+
def arg_responds_to(method, *args)
|
14
|
+
arg_type Symbol, method
|
15
|
+
args.each{|obj| raise ArgumentError, "Object #{obj} (class #{obj.class}) doesn't respond to #{method}." unless obj.respond_to? method}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Require that all arguments be non-nil.
|
19
|
+
def arg_required(*args)
|
20
|
+
args.each{|obj| raise ArgumentError, "Argument cannot be nil" if obj.nil? }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Require that the second argument be non-nil. Upon failure the first argument is used in the error message.
|
24
|
+
def named_arg_required(name, obj)
|
25
|
+
named_arg_required('name', name) unless name.eql?('name')
|
26
|
+
raise ArgumentError, "Argument \"#{name}\" cannot be nil" if obj.nil?
|
27
|
+
end
|
28
|
+
|
29
|
+
# Require that all values in the hash be non-nil. Returns the list of all keys whose values were nil.
|
30
|
+
def named_args_required(obj_hash)
|
31
|
+
keys_with_nil_values = obj_hash.select{|k,v| v.nil?}.collect{|e| e[0]}
|
32
|
+
raise ArgumentError, "Nil argument not allowed in #{keys_with_nil_values.join(', ')}" unless keys_with_nil_values.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
# Require that all arguments be greater than or equal to max.
|
36
|
+
def arg_max(max, *args)
|
37
|
+
args.each{|obj| raise ArgumentError, "Argument exceeds maxmimum value (max is #{max.to_s})" unless max >= obj}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Require that all arguments be less than or equal to min.
|
41
|
+
def arg_min(min, *args)
|
42
|
+
args.each{|obj| raise ArgumentError, "Argument is lower than minimum value (min is #{min.to_s})" unless min <= obj }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Require that all arguments return a set of keys containing at least the specified elements.
|
46
|
+
def arg_hash_keys_required(required_keys, *args)
|
47
|
+
args.each do |h|
|
48
|
+
missing = required_keys - h.keys
|
49
|
+
raise ArgumentError, "Hash is missing required keys (#{missing.join(', ')}). Got:\n#{h.inspect}" if missing.length > 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Require that all arguments return a set of keys containing exactly the specified elements.
|
54
|
+
def arg_hash_keys_exact(exact_keys, *args)
|
55
|
+
args.each do |h|
|
56
|
+
missing = exact_keys - h.keys
|
57
|
+
extra = h.keys - exact_keys
|
58
|
+
raise ArgumentError, "Hash keys don't match required set (#{exact_keys.join(', ')}). " +
|
59
|
+
"Missing required keys (#{missing.join(', ')}); extra keys not allowed (#{extra.join(', ')}).\n" +
|
60
|
+
"Got:\n#{h.inspect}" if (missing.length > 0) || (extra.length >0)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Require that all arguments return a set of keys containing a set of required keys, zero or more of the optional keys, and nothing else.
|
65
|
+
def arg_hash_keys_limit(required_keys, optional_keys, *args)
|
66
|
+
args.each do |h|
|
67
|
+
missing = required_keys - h.keys
|
68
|
+
extra = h.keys - required_keys - optional_keys
|
69
|
+
|
70
|
+
unless missing.empty? && extra.empty?
|
71
|
+
msg = ""
|
72
|
+
msg << "Hash is missing required keys (#{missing.join(', ')}).\n" unless missing.empty?
|
73
|
+
msg << "Hash has extra keys which aren't allowed (#{extra.join(', ')}).\n" unless extra.empty?
|
74
|
+
msg << " Got: #{h.inspect}"
|
75
|
+
raise ArgumentError, msg
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/arg_checks'
|
2
|
+
require File.dirname(__FILE__) + '/array_extensions'
|
3
|
+
require File.dirname(__FILE__) + '/die'
|
4
|
+
require File.dirname(__FILE__) + '/float_extensions'
|
5
|
+
require File.dirname(__FILE__) + '/hash_extensions'
|
6
|
+
require File.dirname(__FILE__) + '/string_extensions'
|
7
|
+
require File.dirname(__FILE__) + '/text_formatter'
|
8
|
+
require File.dirname(__FILE__) + '/time_extensions'
|
9
|
+
require File.dirname(__FILE__) + '/uri_extensions'
|
10
|
+
|
11
|
+
class AvantiConveniences
|
12
|
+
VERSION = '1.0.6'
|
13
|
+
end
|
data/lib/die.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
class Hash
|
2
|
+
# Call a block for every key in the Hash, and replace each key with the block's return value.
|
3
|
+
# This returns a new Hash, so you do not need to call #rehash on it.
|
4
|
+
def map_keys(&block)
|
5
|
+
Hash[* self.to_a.map{|k,v| [yield(k), v] }.flatten ]
|
6
|
+
end
|
7
|
+
alias_method :rekey, :map_keys unless Hash.new.respond_to? :rekey
|
8
|
+
|
9
|
+
# Call a block for every value in the Hash, and replace each value with the block's return value.
|
10
|
+
def map_values(&block)
|
11
|
+
Hash[* self.to_a.map{|k,v| [k, yield(v)] }.flatten ]
|
12
|
+
end
|
13
|
+
alias_method :revalue, :map_keys unless Hash.new.respond_to? :revalue
|
14
|
+
|
15
|
+
# Call a block for every (key, value) pair in the hash, passing them in as a 2-element Array.
|
16
|
+
# The block should return a similar 2-element array of (key, value) which will be used to replace
|
17
|
+
# the original key and value.
|
18
|
+
def map_pairs(&block)
|
19
|
+
Hash[* self.to_a.map{|k,v| yield(k,v) }.flatten ]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'activesupport', '>= 1.2.6'
|
3
|
+
require 'active_support' # for titleize
|
4
|
+
|
5
|
+
class String
|
6
|
+
# Convert a string consisting of whitespace separated words into an underscore-delimited
|
7
|
+
# set of lowercase words. This is the opposite of what ActiveSupport's String.humanize
|
8
|
+
# method docs.
|
9
|
+
# Example: 'Foo Bar' -> 'foo_bar'
|
10
|
+
def dehumanize
|
11
|
+
titleize.gsub(/\W+/,'_').gsub(/\s+/,'_').gsub(/^_+|_+$/,'').underscore
|
12
|
+
end
|
13
|
+
|
14
|
+
# Return this string, surrounded by quote_char on either side.
|
15
|
+
def quote(quote_char)
|
16
|
+
"#{quote_char}#{self}#{quote_char}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return this string, surrounded by a single quote (') on either side.
|
20
|
+
def single_quote; self.quote("'"); end
|
21
|
+
|
22
|
+
# Return this string, surrounded by a double quote (") on either side.
|
23
|
+
def double_quote; self.quote('"'); end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
# Note: Text::Hyphen 1.0.0 uses attr_accessor in a couple of places
|
4
|
+
# where it should use attr_reader, because a setter is defined
|
5
|
+
# immediately afterward; this causes 'method redefined' warnings
|
6
|
+
# when running 'rake test' since the Hoe gem enables the ruby -w flag.
|
7
|
+
# To fix this warning, Text::Hyphen must be fixed. so...
|
8
|
+
# TODO patch Text::Hyphen to fix the 'method redefined' warnings.
|
9
|
+
gem 'text-hyphen', '>= 1.0.0'
|
10
|
+
require 'text/hyphen'
|
11
|
+
|
12
|
+
# Several methods take a language_code argument. This is the language code
|
13
|
+
# (like 'en_us') required by Text::Hyphen.
|
14
|
+
class TextFormatter
|
15
|
+
# Replace all words longer than max_width with the results of split_word.
|
16
|
+
# Leading and trailing whitespace is eliminated and inline whitespace runs are replaced with a space.
|
17
|
+
def split_long_words(string, max_width, language_code, append_newlines = false)
|
18
|
+
words = string.split
|
19
|
+
words.collect{|w| w.length > max_width ? split_word(w, max_width, language_code, append_newlines) : w}.flatten.join(' ')
|
20
|
+
end
|
21
|
+
|
22
|
+
# Split one word and return it as an array of substrings no longer than the specified size.
|
23
|
+
# Splitting results consist of a hyphenated version (if possible) or by cutting the word into
|
24
|
+
# segments no longer than max_width (if hyphenation fails, such as for the word 'xxxxxxxxxxx')
|
25
|
+
# Every substring except the last will have a newline appended unless append_newlines is false.
|
26
|
+
# The result for a 'word' string containing whitespace is undefined.
|
27
|
+
def split_word(word, size, langauge_code, append_newlines = true)
|
28
|
+
hyphenated = hyphenate_word(word,size,langauge_code)
|
29
|
+
hyphenated_chopped = hyphenated.collect{|w| w.length > size ? chop_word(w, size) : w}.flatten
|
30
|
+
if append_newlines
|
31
|
+
hyphenated_chopped.collect!{|w| "#{w}\n"}
|
32
|
+
hyphenated_chopped.last.chop!
|
33
|
+
end
|
34
|
+
return hyphenated_chopped
|
35
|
+
end
|
36
|
+
|
37
|
+
# Try to hyphenate a word into chunks just barely short enough to fit within the specified size
|
38
|
+
def hyphenate_word(word, size, language_code)
|
39
|
+
# handle pre-hyphenated words, which hyphenate_to balks on
|
40
|
+
hyphenated = word.split(/-/)
|
41
|
+
if hyphenated.size > 1
|
42
|
+
hyphenated.collect!{|w| w.length > size ? self.hyphenate_word(w, size, language_code) : w}
|
43
|
+
hyphenated.flatten!
|
44
|
+
last = hyphenated.pop
|
45
|
+
hyphenated.collect!{|w| w[-1,1].eql?('-') ? w : "#{w}-"}
|
46
|
+
hyphenated.push(last)
|
47
|
+
return hyphenated
|
48
|
+
end
|
49
|
+
|
50
|
+
h = TextFormatter.text_hyphenator(language_code)
|
51
|
+
hyphenated = h.hyphenate_to(word, size).compact
|
52
|
+
|
53
|
+
loop_limit = word.length
|
54
|
+
while (hyphenated.size > 1 && hyphenated.last.length > size) do
|
55
|
+
last = hyphenated.pop
|
56
|
+
part1, part2 = h.hyphenate_to(last, size).compact
|
57
|
+
hyphenated.push(part1)
|
58
|
+
hyphenated.push(part2) unless part2.nil?
|
59
|
+
|
60
|
+
loop_limit -= 1
|
61
|
+
break if last.eql?(part1) || (loop_limit < 0)
|
62
|
+
end
|
63
|
+
return hyphenated
|
64
|
+
end
|
65
|
+
|
66
|
+
# Simply chop overly long "words" into chunks no longer than the specified size
|
67
|
+
def chop_word(word, size)
|
68
|
+
chopped = []
|
69
|
+
while (!word.nil? && word.length > size) do
|
70
|
+
chopped.push word[0,size]
|
71
|
+
word = word[size..-1]
|
72
|
+
end
|
73
|
+
chopped.push(word) # get the last chunk
|
74
|
+
return chopped
|
75
|
+
end
|
76
|
+
|
77
|
+
# Get a Text::Hyphen instance for a specified language
|
78
|
+
def TextFormatter.text_hyphenator(language_code)
|
79
|
+
@@hyphenators = Hash.new unless defined? @@hyphenators
|
80
|
+
@@hyphenators[language_code] ||= Text::Hyphen.new(:language => language_code, :left => 2, :right => 2)
|
81
|
+
return @@hyphenators[language_code]
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'activesupport'
|
3
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
4
|
+
|
5
|
+
require 'uri'
|
6
|
+
require File.dirname(__FILE__) + '/hash_extensions'
|
7
|
+
|
8
|
+
class URI::Generic
|
9
|
+
# Create a URI query string from a Hash. The keys in the returned query string
|
10
|
+
# are sorted for easier testing.
|
11
|
+
# Example: {:foo => 'bar', :biz => 'b a z'} -> '?biz=b%20a%20z&foo=bar'
|
12
|
+
def self.query_from_hash(q_hash)
|
13
|
+
return '' if q_hash.nil?
|
14
|
+
|
15
|
+
# Reveal cases where the caller thought they were using HashWithIndifferentAccess
|
16
|
+
# but actually they used Hash and probably got duplicate keys (:foo vs 'foo')
|
17
|
+
q_hash = q_hash.rekey{|k| k.is_a?(Symbol) ? ":#{k}" : k} unless q_hash.is_a?(HashWithIndifferentAccess)
|
18
|
+
|
19
|
+
pairs = []
|
20
|
+
q_hash.each_pair{|k,v| pairs << "#{k}=#{URI.escape(v.to_s)}" unless v.nil?}
|
21
|
+
'?' + pairs.sort.join('&')
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/arg_checks'
|
3
|
+
|
4
|
+
class TestArgChecks < Test::Unit::TestCase
|
5
|
+
include ArgChecks
|
6
|
+
|
7
|
+
def test_arg_type
|
8
|
+
assert_nothing_raised(ArgumentError) { arg_dummy('s', 3.0) }
|
9
|
+
assert_raise(ArgumentError) { arg_dummy('s', 3) }
|
10
|
+
assert_raise(ArgumentError) { arg_dummy('blah blah', 'x') }
|
11
|
+
assert_raise(ArgumentError) { arg_dummy(3.0, 3.0) }
|
12
|
+
|
13
|
+
assert_nothing_raised(ArgumentError) { arg_dummy2('s', -1.0, 10.0, 'x') }
|
14
|
+
assert_raise(ArgumentError) { arg_dummy2(-1.0, 10.0, 'x', 'blah') }
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_arg_required
|
18
|
+
assert_raise(ArgumentError) { arg_dummy5(nil, nil) }
|
19
|
+
assert_raise(ArgumentError) { arg_dummy5(nil, 3.0) }
|
20
|
+
assert_raise(ArgumentError) { arg_dummy5('blah', nil) }
|
21
|
+
assert_nothing_raised(ArgumentError) { arg_dummy5('blah', 3.0) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def arg_dummy5(arg1, arg2)
|
25
|
+
arg_required arg1, arg2
|
26
|
+
end
|
27
|
+
|
28
|
+
def arg_dummy(arg1_string, arg2_float)
|
29
|
+
arg_type String, arg1_string
|
30
|
+
arg_type Float, arg2_float
|
31
|
+
end
|
32
|
+
|
33
|
+
def arg_dummy2(arg1_string, arg2_float, arg3_float, arg4_string)
|
34
|
+
arg_type String, arg1_string, arg4_string
|
35
|
+
arg_type Float, arg2_float, arg3_float
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_arg_min
|
39
|
+
assert_raise(ArgumentError) {arg_dummy3(5, 'z')}
|
40
|
+
assert_raise(ArgumentError) {arg_dummy3(100, 'x')}
|
41
|
+
assert_nothing_raised(ArgumentError) {arg_dummy3(100, 'z')}
|
42
|
+
end
|
43
|
+
|
44
|
+
def arg_dummy3(arg1, arg2)
|
45
|
+
arg_min 6, arg1
|
46
|
+
arg_min 'y', arg2
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_arg_max
|
50
|
+
assert_raise(ArgumentError) {arg_dummy4(100, 'z')}
|
51
|
+
assert_raise(ArgumentError) {arg_dummy4(5, 'z')}
|
52
|
+
assert_nothing_raised(ArgumentError) {arg_dummy4(5, 'x')}
|
53
|
+
end
|
54
|
+
|
55
|
+
def arg_dummy4(arg1, arg2)
|
56
|
+
arg_max 6, arg1
|
57
|
+
arg_max 'y', arg2
|
58
|
+
end
|
59
|
+
|
60
|
+
@@hash = {'k1' => 'v1', 'k2'=>'v2'}
|
61
|
+
|
62
|
+
def test_arg_hash_keys_exact
|
63
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_exact %w{k1 k2}, @@hash }
|
64
|
+
|
65
|
+
assert_raise(ArgumentError) { arg_hash_keys_exact %w{k1}, @@hash}
|
66
|
+
assert_raise(ArgumentError) { arg_hash_keys_exact %w{k2}, @@hash }
|
67
|
+
assert_raise(ArgumentError) { arg_hash_keys_exact %w{k1 k2 k3}, @@hash }
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_arg_hash_keys_required
|
71
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_required %w{k1 k2}, @@hash }
|
72
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_required %w{k1}, @@hash }
|
73
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_required %w{k2}, @@hash }
|
74
|
+
|
75
|
+
assert_raise(ArgumentError) { arg_hash_keys_required %w{k1 k2 k3}, @@hash }
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_arg_hash_keys_limit
|
79
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_limit %w{k1 k2}, %w{k3}, @@hash }
|
80
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_limit %w{k1}, %w{k2 k3}, @@hash }
|
81
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_limit %w{k2}, %w{k1 k3}, @@hash }
|
82
|
+
assert_nothing_raised(ArgumentError) { arg_hash_keys_limit [], %w{k1 k2 k3}, @@hash }
|
83
|
+
|
84
|
+
assert_raise(ArgumentError) { arg_hash_keys_limit %w{k1 k2 k3}, [], @@hash }
|
85
|
+
assert_raise(ArgumentError) { arg_hash_keys_limit %w{k1 k3}, %w{k2}, @@hash }
|
86
|
+
assert_raise(ArgumentError) { arg_hash_keys_limit %w{k3}, %w{k1, k2}, @@hash }
|
87
|
+
assert_raise(ArgumentError) { arg_hash_keys_limit [], [], @@hash }
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_named_arg_required
|
91
|
+
assert_nothing_raised(ArgumentError){ named_arg_required('foo', 1) }
|
92
|
+
assert_raise(ArgumentError){ named_arg_required('bar', nil) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_named_args_required
|
96
|
+
assert_nothing_raised(ArgumentError){ named_args_required({}) }
|
97
|
+
assert_nothing_raised(ArgumentError){ named_args_required(:foo => 1) }
|
98
|
+
assert_raise(ArgumentError){ named_args_required(:bar => nil) }
|
99
|
+
assert_raise(ArgumentError){ named_args_required(:foo => 1, :bar => nil) }
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_arg_respond_to
|
103
|
+
assert_nothing_raised(ArgumentError) { arg_dummy6(:round, 1.1) }
|
104
|
+
assert_nothing_raised(ArgumentError) { arg_dummy6(:round, Float::EPSILON) }
|
105
|
+
assert_raise(ArgumentError) { arg_dummy6(:round, 'a') }
|
106
|
+
assert_raise(ArgumentError) { arg_dummy6(:round, [0]) }
|
107
|
+
assert_raise(ArgumentError) { arg_dummy6(:round, Object) }
|
108
|
+
end
|
109
|
+
|
110
|
+
def arg_dummy6(arg1, arg2)
|
111
|
+
arg_responds_to arg1, arg2
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/array_extensions'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
module StringMath
|
6
|
+
def +(other)
|
7
|
+
result = super(other)
|
8
|
+
result.extend StringMath
|
9
|
+
result
|
10
|
+
end
|
11
|
+
|
12
|
+
def /(denominator)
|
13
|
+
chunk_size = (self.size.to_f / denominator).to_i
|
14
|
+
self[0..(chunk_size - 1)]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
class TestArrayExtensions < Test::Unit::TestCase
|
20
|
+
|
21
|
+
context 'Array.average' do
|
22
|
+
should 'return the average of 3 integers' do
|
23
|
+
assert_equal 5, [1,3,11].average
|
24
|
+
end
|
25
|
+
|
26
|
+
should 'return the average of 3 floats' do
|
27
|
+
assert_equal 5.21, [1.1, 3.3, 11.23].average
|
28
|
+
end
|
29
|
+
|
30
|
+
should 'work on anything that supports + and / operators' do
|
31
|
+
test_data = [1,3,11].map{|n| ('x' * n).extend StringMath}
|
32
|
+
assert_equal 'xxxxx', test_data.average
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/test/test_die.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/die'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
class TestDie < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context 'Die.roll' do
|
8
|
+
setup do
|
9
|
+
seed = 1234567890
|
10
|
+
srand(seed)
|
11
|
+
@expected_rand = rand
|
12
|
+
srand(seed)
|
13
|
+
end
|
14
|
+
|
15
|
+
should 'return a value between 1 and the number of sides' do
|
16
|
+
sides = 1000
|
17
|
+
expected = (@expected_rand * sides + 1).to_i
|
18
|
+
assert_equal expected, Die.roll(sides)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/float_extensions'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
class TestFloatExtensions < Test::Unit::TestCase
|
6
|
+
|
7
|
+
context 'Float::INFINITY' do
|
8
|
+
should 'be greater than 10**100' do
|
9
|
+
assert Float::INFINITY > 10**100
|
10
|
+
end
|
11
|
+
should 'be equal to the absolute value of negative infinity' do
|
12
|
+
negative_infinity = -1.0 / 0
|
13
|
+
assert_equal negative_infinity.abs, Float::INFINITY
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/hash_extensions'
|
3
|
+
|
4
|
+
class TestHashExtensions < Test::Unit::TestCase
|
5
|
+
def test_map_keys
|
6
|
+
expected = {10 => :a, 20 => :b}
|
7
|
+
actual = {1 => :a, 2 => :b}.map_keys{|k| k * 10}
|
8
|
+
assert_equal expected, actual
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_map_values
|
12
|
+
expected = {:a => 10, :b => 20}
|
13
|
+
actual = {:a => 1, :b => 2}.map_values{|k| k * 10}
|
14
|
+
assert_equal expected, actual
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_map_pairs
|
18
|
+
expected = {'A' => 10, 'B' => 20}
|
19
|
+
actual = {'a' => 1, 'b' => 2}.map_pairs{|k, v| [k.upcase, v * 10] }
|
20
|
+
assert_equal expected, actual
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/string_extensions'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
gem 'activesupport', '>= 1.2.6'
|
6
|
+
require 'active_support' # for .humanize
|
7
|
+
|
8
|
+
class TestStringExtensions < Test::Unit::TestCase
|
9
|
+
context 'String#dehumanize' do
|
10
|
+
[ ['Hello, World', 'hello_world'],
|
11
|
+
['$$$123#456', '123_456'],
|
12
|
+
['a_b_c_', 'a_b_c'],
|
13
|
+
['/etc/passwd', 'etc_passwd'],
|
14
|
+
['Foo', 'foo'],
|
15
|
+
['Foo Bar', 'foo_bar'],
|
16
|
+
['Foo_Bar', 'foo_bar'],
|
17
|
+
["foo\tbar\nbiz \t\n\t \n\t\n baz_ ", 'foo_bar_biz_baz'],
|
18
|
+
].each do |input, expected|
|
19
|
+
should("convert #{input} into #{expected}") do
|
20
|
+
assert_equal expected, input.dehumanize
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
%w{1 x hello_world 123_456 foo_bar}.each do |round_trippable|
|
25
|
+
should "undo humanize(#{round_trippable})" do
|
26
|
+
assert_equal round_trippable, round_trippable.humanize.dehumanize
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
['1', 'X', 'A herring', 'Hello world'].each do |rehumanizable|
|
31
|
+
should "return a value for #{rehumanizable} that humanize can undo correctly" do
|
32
|
+
assert_equal rehumanizable, rehumanizable.dehumanize.humanize
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_quote
|
41
|
+
d = {'Foo' => '~Foo~',
|
42
|
+
'Foo~' => '~Foo~~',
|
43
|
+
'Foo Bar' => '~Foo Bar~'}
|
44
|
+
d.each{|i,o| assert_equal o, i.quote('~')}
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_single_quote
|
48
|
+
d = {'Foo Bar' => "'Foo Bar'"}
|
49
|
+
d.each{|i,o| assert_equal o, i.single_quote}
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_double_quote
|
53
|
+
d = {'Foo Bar' => '"Foo Bar"'}
|
54
|
+
d.each{|i,o| assert_equal o, i.double_quote}
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/text_formatter'
|
3
|
+
|
4
|
+
class TestTextFormatter < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@tf = TextFormatter.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_chop_word_1
|
10
|
+
assert_equal %w{xxx xxx xxx x}, @tf.chop_word('xxxxxxxxxx', 3)
|
11
|
+
end
|
12
|
+
def test_chop_word_2
|
13
|
+
assert_equal %w{xxx xx}, @tf.chop_word('xxxxx', 3)
|
14
|
+
end
|
15
|
+
def test_chop_word_3
|
16
|
+
assert_equal %w{xx}, @tf.chop_word('xx', 3)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_hyphenate_word_1
|
20
|
+
assert_equal ["Hobo-", 'ken'], @tf.hyphenate_word('Hoboken',5,'en_us')
|
21
|
+
end
|
22
|
+
def test_hyphenate_word_2
|
23
|
+
assert_equal ["spectac-", 'ular'], @tf.hyphenate_word('spectacular',8,'en_us')
|
24
|
+
end
|
25
|
+
def test_hyphenate_word_3
|
26
|
+
assert_equal ["antidisestab-","lishmentarian-","ism"], @tf.hyphenate_word('antidisestablishmentarianism', 15, 'en_us')
|
27
|
+
end
|
28
|
+
def test_hyphenate_word_4
|
29
|
+
x = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
30
|
+
assert_equal [x], @tf.hyphenate_word(x, 5, 'en_us')
|
31
|
+
end
|
32
|
+
|
33
|
+
# Real words
|
34
|
+
def test_split_word_1
|
35
|
+
assert_equal ["Hobo-\n", 'ken'], @tf.split_word('Hoboken',5,'en_us')
|
36
|
+
end
|
37
|
+
def test_split_word_2
|
38
|
+
assert_equal ["spectac-\n", 'ular'], @tf.split_word('spectacular',8,'en_us')
|
39
|
+
end
|
40
|
+
def test_split_word_3
|
41
|
+
assert_equal ["spectac-", 'ular'], @tf.split_word('spectacular',8,'en_us', false)
|
42
|
+
end
|
43
|
+
def test_split_word_4
|
44
|
+
assert_equal ["antidisestab-\n","lishmentarian-\n","ism"], @tf.split_word('antidisestablishmentarianism', 15, 'en_us')
|
45
|
+
end
|
46
|
+
def test_split_word_5
|
47
|
+
assert_equal ["antidisestab-","lishmentarian-","ism"], @tf.split_word('antidisestablishmentarianism', 15, 'en_us', false)
|
48
|
+
end
|
49
|
+
|
50
|
+
# long strings get chopped
|
51
|
+
def test_split_word_6
|
52
|
+
x = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
53
|
+
split_x = []
|
54
|
+
15.times{split_x.push("xxxxx\n")}
|
55
|
+
split_x.push('x')
|
56
|
+
assert_equal split_x, @tf.split_word(x, 5, 'en_us')
|
57
|
+
end
|
58
|
+
|
59
|
+
# pre-hyphenated words should be easy to handle
|
60
|
+
def test_split_word_7
|
61
|
+
assert_equal ["prepared-","from-","recipe"], @tf.split_word('prepared-from-recipe', 15, 'en_us', false)
|
62
|
+
end
|
63
|
+
def test_split_word_8
|
64
|
+
assert_equal ["pre-","pared-","from-","recipe"], @tf.split_word('prepared-from-recipe', 6, 'en_us', false)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_split_long_words_1
|
68
|
+
assert_equal "Hobo- ken", @tf.split_long_words('Hoboken',5,'en_us')
|
69
|
+
end
|
70
|
+
def test_split_long_words_2
|
71
|
+
assert_equal "spectac- ular", @tf.split_long_words('spectacular',8,'en_us')
|
72
|
+
end
|
73
|
+
def test_split_long_words_3
|
74
|
+
assert_equal "antidisestab- lishmentarian- ism", @tf.split_long_words('antidisestablishmentarianism', 15, 'en_us')
|
75
|
+
end
|
76
|
+
def test_split_long_words_4
|
77
|
+
i = ["Hoboken New Jersey \n\n \t is a\t \nnice \n\t\n\t place.",5,'en_us']
|
78
|
+
o = "Hobo- ken New Jer- sey is a nice place ."
|
79
|
+
assert_equal o, @tf.split_long_words(*i)
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/array_extensions'
|
3
|
+
require 'shoulda'
|
4
|
+
|
5
|
+
gem 'activesupport', '>= 1.2.6'
|
6
|
+
require 'active_support' # for .hour, .hours, .second
|
7
|
+
|
8
|
+
class TestArrayExtensions < Test::Unit::TestCase
|
9
|
+
|
10
|
+
context 'Time#at_midnight' do
|
11
|
+
[ ['2009-12-01 01:00:00', 1.hour ],
|
12
|
+
['2009-12-01 00:00:00', 0 ],
|
13
|
+
['2009-12-01 23:59:59', (24.hours - 1.second) ],
|
14
|
+
].each do |input, expected|
|
15
|
+
should "be #{expected} seconds before #{input}" do
|
16
|
+
t = Time.parse(input)
|
17
|
+
assert_equal expected, t - t.at_midnight
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/uri_extensions'
|
3
|
+
|
4
|
+
class TestUriExtensions < Test::Unit::TestCase
|
5
|
+
def test_uri_generic_query_from_hash
|
6
|
+
assert_equal '?a=1&b=2', URI::Generic.query_from_hash('a'=>1, 'b'=>2)
|
7
|
+
assert_equal '?:a=1&a=11&b=2', URI::Generic.query_from_hash(:a=>1, 'b'=>2, 'a'=>11)
|
8
|
+
assert_equal '?biz=b%20a%20z&foo=bar', URI::Generic.query_from_hash('foo' => 'bar', 'biz' => 'b a z')
|
9
|
+
|
10
|
+
h = HashWithIndifferentAccess.new
|
11
|
+
h.merge! :a=>1, :b=>2
|
12
|
+
assert_equal '?a=1&b=2', URI::Generic.query_from_hash(h)
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: AvantiConveniences
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jamie Flournoy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-22 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.6
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: text-hyphen
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: thoughtbot-shoulda
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.10.1
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: hoe
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.3.3
|
54
|
+
version:
|
55
|
+
description: AvantiConveniences is a set of convenience code for Ruby on Rails applications.
|
56
|
+
email:
|
57
|
+
- jamie@pervasivecode.com
|
58
|
+
executables: []
|
59
|
+
|
60
|
+
extensions: []
|
61
|
+
|
62
|
+
extra_rdoc_files:
|
63
|
+
- History.txt
|
64
|
+
- Manifest.txt
|
65
|
+
- README.txt
|
66
|
+
files:
|
67
|
+
- AvantiConveniences.gemspec
|
68
|
+
- History.txt
|
69
|
+
- Manifest.txt
|
70
|
+
- README.txt
|
71
|
+
- Rakefile
|
72
|
+
- lib/arg_checks.rb
|
73
|
+
- lib/array_extensions.rb
|
74
|
+
- lib/avanti_conveniences.rb
|
75
|
+
- lib/die.rb
|
76
|
+
- lib/float_extensions.rb
|
77
|
+
- lib/hash_extensions.rb
|
78
|
+
- lib/string_extensions.rb
|
79
|
+
- lib/text_formatter.rb
|
80
|
+
- lib/time_extensions.rb
|
81
|
+
- lib/uri_extensions.rb
|
82
|
+
- test/test_arg_checks.rb
|
83
|
+
- test/test_array_extensions.rb
|
84
|
+
- test/test_avanti_conveniences.rb
|
85
|
+
- test/test_die.rb
|
86
|
+
- test/test_float_extensions.rb
|
87
|
+
- test/test_hash_extensions.rb
|
88
|
+
- test/test_string_extensions.rb
|
89
|
+
- test/test_text_formatter.rb
|
90
|
+
- test/test_time_extensions.rb
|
91
|
+
- test/test_uri_extensions.rb
|
92
|
+
has_rdoc: true
|
93
|
+
homepage: http://www.pervasivecode.com/blog/avanticonveniences/
|
94
|
+
licenses: []
|
95
|
+
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options:
|
98
|
+
- --main
|
99
|
+
- README.txt
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: "0"
|
107
|
+
version:
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: "0"
|
113
|
+
version:
|
114
|
+
requirements: []
|
115
|
+
|
116
|
+
rubyforge_project: avanticonveniences
|
117
|
+
rubygems_version: 1.3.5
|
118
|
+
signing_key:
|
119
|
+
specification_version: 3
|
120
|
+
summary: AvantiConveniences is a set of convenience code for Ruby on Rails applications.
|
121
|
+
test_files:
|
122
|
+
- test/test_arg_checks.rb
|
123
|
+
- test/test_array_extensions.rb
|
124
|
+
- test/test_avanti_conveniences.rb
|
125
|
+
- test/test_die.rb
|
126
|
+
- test/test_float_extensions.rb
|
127
|
+
- test/test_hash_extensions.rb
|
128
|
+
- test/test_string_extensions.rb
|
129
|
+
- test/test_text_formatter.rb
|
130
|
+
- test/test_time_extensions.rb
|
131
|
+
- test/test_uri_extensions.rb
|