JamieFlournoy-AvantiConveniences 1.0.4

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