JamieFlournoy-AvantiConveniences 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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!
@@ -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
@@ -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.
@@ -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
@@ -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/avanti_conveniences'
3
+
4
+ class TestAvantiConveniences < Test::Unit::TestCase
5
+ def test_version
6
+ assert defined? AvantiConveniences::VERSION
7
+ assert_not_nil AvantiConveniences::VERSION
8
+ end
9
+ 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