JamieFlournoy-AvantiConveniences 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +23 -0
- data/Manifest.txt +16 -0
- data/README.txt +69 -0
- data/Rakefile +74 -0
- data/lib/arg_checks.rb +79 -0
- data/lib/avanti_conveniences.rb +9 -0
- data/lib/hash_extensions.rb +10 -0
- data/lib/string_extensions.rb +24 -0
- data/lib/text_formatter.rb +83 -0
- data/lib/uri_extensions.rb +23 -0
- data/test/test_arg_checks.rb +113 -0
- data/test/test_avanti_conveniences.rb +9 -0
- data/test/test_hash_extensions.rb +9 -0
- data/test/test_string_extensions.rb +30 -0
- data/test/test_text_formatter.rb +81 -0
- data/test/test_uri_extensions.rb +14 -0
- metadata +106 -0
data/History.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
=== 1.0.4 / 2009-03-20
|
2
|
+
|
3
|
+
* Fixed the 'rcov' Rake task so it worked with the latest Hoe.
|
4
|
+
* Added a bit of documentation that was missing.
|
5
|
+
|
6
|
+
=== 1.0.3 / 2008-11-11
|
7
|
+
|
8
|
+
* Bug fix for a hang in TextFormatter.hyphenate_word, when given a wprd that contains multiple hyphens.
|
9
|
+
|
10
|
+
=== 1.0.2 / 2008-09-29
|
11
|
+
|
12
|
+
* Made TextFormatter.split_long_words take a fourth optional argument to control insertion of newlines in split text.
|
13
|
+
|
14
|
+
=== 1.0.1 / 2008-08-30
|
15
|
+
|
16
|
+
* Changed the output of ArgChecks.arg_type so that it includes the to_s representation of the object itself in the exception message.
|
17
|
+
* Added ArgChecks.arg_responds_to.
|
18
|
+
|
19
|
+
=== 1.0.0 / 2008-08-04
|
20
|
+
|
21
|
+
* First release.
|
22
|
+
|
23
|
+
* Birthday!
|
data/Manifest.txt
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
lib/arg_checks.rb
|
6
|
+
lib/avanti_conveniences.rb
|
7
|
+
lib/hash_extensions.rb
|
8
|
+
lib/string_extensions.rb
|
9
|
+
lib/text_formatter.rb
|
10
|
+
lib/uri_extensions.rb
|
11
|
+
test/test_arg_checks.rb
|
12
|
+
test/test_avanti_conveniences.rb
|
13
|
+
test/test_hash_extensions.rb
|
14
|
+
test/test_string_extensions.rb
|
15
|
+
test/test_text_formatter.rb
|
16
|
+
test/test_uri_extensions.rb
|
data/README.txt
ADDED
@@ -0,0 +1,69 @@
|
|
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
|
+
HashExtensions currently just adds the Hash#rekey method.
|
17
|
+
|
18
|
+
StringExtensions provides String quoting (not escaping) with single quotes,
|
19
|
+
double quotes, or a caller-specified quoting character, and a String#dehumanize
|
20
|
+
method to do the reverse of the String#humanize method provided by ActiveSupport.
|
21
|
+
|
22
|
+
TextFormatter provides methods for hyphenating words for word-wrapping.
|
23
|
+
|
24
|
+
URIExtensions provides URI::Generic#query_from_hash, which will create a URI
|
25
|
+
query string from a Hash.
|
26
|
+
|
27
|
+
== SYNOPSIS:
|
28
|
+
|
29
|
+
See individual classes for details. All of them are single method invocations
|
30
|
+
that are very simple to use. For additional examples look in the test/
|
31
|
+
directory.
|
32
|
+
|
33
|
+
== REQUIREMENTS:
|
34
|
+
|
35
|
+
Ruby 1.8.5 (might work with earlier versions), ActiveSupport 1.2.6, Text-Hyphen
|
36
|
+
1.0.0, and Hoe 1.7.0.
|
37
|
+
|
38
|
+
== INSTALL:
|
39
|
+
|
40
|
+
If you haven't done this before:
|
41
|
+
gem sources -a http://gems.github.com
|
42
|
+
|
43
|
+
Then:
|
44
|
+
sudo gem install JamieFlournoy-AvantiConveniences
|
45
|
+
|
46
|
+
== LICENSE:
|
47
|
+
|
48
|
+
(The MIT License)
|
49
|
+
|
50
|
+
Copyright (c) 2008 Pervasive Code
|
51
|
+
|
52
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
53
|
+
a copy of this software and associated documentation files (the
|
54
|
+
'Software'), to deal in the Software without restriction, including
|
55
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
56
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
57
|
+
permit persons to whom the Software is furnished to do so, subject to
|
58
|
+
the following conditions:
|
59
|
+
|
60
|
+
The above copyright notice and this permission notice shall be
|
61
|
+
included in all copies or substantial portions of the Software.
|
62
|
+
|
63
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
64
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
65
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
66
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
67
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
68
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
69
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/avanti_conveniences.rb'
|
6
|
+
|
7
|
+
hoe = Hoe.new('AvantiConveniences', AvantiConveniences::VERSION) do |p|
|
8
|
+
p.developer('Jamie Flournoy', 'jamie@pervasivecode.com')
|
9
|
+
p.extra_deps = [['activesupport', '>= 1.2.6'], ['text-hyphen', '>= 1.0.0']]
|
10
|
+
end
|
11
|
+
|
12
|
+
task :gemspec do
|
13
|
+
File.open("#{hoe.name}.gemspec", "w") {|f| f << hoe.spec.to_ruby }
|
14
|
+
end
|
15
|
+
task :package => :gemspec
|
16
|
+
|
17
|
+
|
18
|
+
# The rcov task in this file worked until Hoe was updated; this code keeps the old behavior
|
19
|
+
# and disables Hoe's rcov task.
|
20
|
+
Rake::TaskManager.class_eval do
|
21
|
+
def remove_task(task_name)
|
22
|
+
@tasks.delete(task_name.to_s)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
def remove_task(task_name)
|
26
|
+
Rake.application.remove_task(task_name)
|
27
|
+
end
|
28
|
+
remove_task 'rcov'
|
29
|
+
|
30
|
+
|
31
|
+
task :rcov do
|
32
|
+
sh 'rcov test/test_*.rb'
|
33
|
+
end
|
34
|
+
task :clean_rcov do
|
35
|
+
sh 'rm -rf ./coverage/*'
|
36
|
+
end
|
37
|
+
task :clean => [:clean_rcov]
|
38
|
+
|
39
|
+
|
40
|
+
# vim: syntax=Ruby
|
41
|
+
|
42
|
+
|
43
|
+
# stats
|
44
|
+
begin
|
45
|
+
gem 'rails'
|
46
|
+
require 'code_statistics'
|
47
|
+
namespace :spec do
|
48
|
+
desc "Use Rails's rake:stats task for a gem"
|
49
|
+
task :statsetup do
|
50
|
+
class CodeStatistics
|
51
|
+
def calculate_statistics
|
52
|
+
@pairs.inject({}) do |stats, pair|
|
53
|
+
if 3 == pair.size
|
54
|
+
stats[pair.first] = calculate_directory_statistics(pair[1], pair[2]); stats
|
55
|
+
else
|
56
|
+
stats[pair.first] = calculate_directory_statistics(pair.last); stats
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
::STATS_DIRECTORIES = [['Libraries', 'lib', /\.(sql|rhtml|erb|rb|yml)$/],
|
62
|
+
['Tests', 'test', /\.(sql|rhtml|erb|rb|yml)$/]]
|
63
|
+
::CodeStatistics::TEST_TYPES << "Tests"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
desc "Report code statistics (KLOCs, etc) from the application"
|
67
|
+
task :stats => "spec:statsetup" do
|
68
|
+
CodeStatistics.new(*STATS_DIRECTORIES).to_s
|
69
|
+
end
|
70
|
+
rescue Gem::LoadError => le
|
71
|
+
task :stats do
|
72
|
+
raise RuntimeError, "'rails' gem not found - you must install it in order to use this task.\n"
|
73
|
+
end
|
74
|
+
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,9 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/arg_checks'
|
2
|
+
require File.dirname(__FILE__) + '/hash_extensions'
|
3
|
+
require File.dirname(__FILE__) + '/string_extensions'
|
4
|
+
require File.dirname(__FILE__) + '/text_formatter'
|
5
|
+
require File.dirname(__FILE__) + '/uri_extensions'
|
6
|
+
|
7
|
+
class AvantiConveniences
|
8
|
+
VERSION = '1.0.4'
|
9
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Hash
|
2
|
+
unless Hash.new.respond_to? :rekey
|
3
|
+
# Return a copy of this Hash where each key is result of calling the block with each key as the argument.
|
4
|
+
def rekey(&block)
|
5
|
+
rekeyed = {}
|
6
|
+
keys.each{|k| rekeyed[yield(k)] = self[k] }
|
7
|
+
rekeyed
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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(/\s/,'').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
|
+
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,9 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/hash_extensions'
|
3
|
+
|
4
|
+
class TestHashExtensions < Test::Unit::TestCase
|
5
|
+
def test_rekey
|
6
|
+
test_data = {{'foo' => 1, 'aBc' => 2} => ['ABC', 'FOO']}
|
7
|
+
test_data.each{|i,o| assert_equal o, i.rekey{|k| k.upcase}.keys.sort }
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/string_extensions'
|
3
|
+
|
4
|
+
class TestStringExtensions < Test::Unit::TestCase
|
5
|
+
def test_dehumanize
|
6
|
+
d = {'Foo' => 'foo',
|
7
|
+
'Foo ' => 'foo',
|
8
|
+
'Foo Bar' => 'foo_bar',
|
9
|
+
'Foo_Bar' => 'foo_bar',
|
10
|
+
"foo\tbar\nbiz \t\n\t \n\t\n baz_ " => 'foo_bar_biz_baz'}
|
11
|
+
d.each{|i,o| assert_equal o, i.dehumanize}
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_quote
|
15
|
+
d = {'Foo' => '~Foo~',
|
16
|
+
'Foo~' => '~Foo~~',
|
17
|
+
'Foo Bar' => '~Foo Bar~'}
|
18
|
+
d.each{|i,o| assert_equal o, i.quote('~')}
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_single_quote
|
22
|
+
d = {'Foo Bar' => "'Foo Bar'"}
|
23
|
+
d.each{|i,o| assert_equal o, i.single_quote}
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_double_quote
|
27
|
+
d = {'Foo Bar' => '"Foo Bar"'}
|
28
|
+
d.each{|i,o| assert_equal o, i.double_quote}
|
29
|
+
end
|
30
|
+
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,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,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: JamieFlournoy-AvantiConveniences
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jamie Flournoy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-03-20 00:00:00 -07: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: hoe
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.11.0
|
44
|
+
version:
|
45
|
+
description: AvantiConveniences is a set of convenience code for Ruby on Rails applications.
|
46
|
+
email:
|
47
|
+
- jamie@pervasivecode.com
|
48
|
+
executables: []
|
49
|
+
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
extra_rdoc_files:
|
53
|
+
- History.txt
|
54
|
+
- Manifest.txt
|
55
|
+
- README.txt
|
56
|
+
files:
|
57
|
+
- History.txt
|
58
|
+
- Manifest.txt
|
59
|
+
- README.txt
|
60
|
+
- Rakefile
|
61
|
+
- lib/arg_checks.rb
|
62
|
+
- lib/avanti_conveniences.rb
|
63
|
+
- lib/hash_extensions.rb
|
64
|
+
- lib/string_extensions.rb
|
65
|
+
- lib/text_formatter.rb
|
66
|
+
- lib/uri_extensions.rb
|
67
|
+
- test/test_arg_checks.rb
|
68
|
+
- test/test_avanti_conveniences.rb
|
69
|
+
- test/test_hash_extensions.rb
|
70
|
+
- test/test_string_extensions.rb
|
71
|
+
- test/test_text_formatter.rb
|
72
|
+
- test/test_uri_extensions.rb
|
73
|
+
has_rdoc: true
|
74
|
+
homepage: http://www.pervasivecode.com/blog/avanticonveniences/
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options:
|
77
|
+
- --main
|
78
|
+
- README.txt
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
version:
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: "0"
|
92
|
+
version:
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project: avanticonveniences
|
96
|
+
rubygems_version: 1.2.0
|
97
|
+
signing_key:
|
98
|
+
specification_version: 2
|
99
|
+
summary: AvantiConveniences is a set of convenience code for Ruby on Rails applications.
|
100
|
+
test_files:
|
101
|
+
- test/test_arg_checks.rb
|
102
|
+
- test/test_avanti_conveniences.rb
|
103
|
+
- test/test_hash_extensions.rb
|
104
|
+
- test/test_string_extensions.rb
|
105
|
+
- test/test_text_formatter.rb
|
106
|
+
- test/test_uri_extensions.rb
|