qualitysmith_extensions 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme +72 -0
- data/lib/qualitysmith_extensions/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +42 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +48 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +112 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +64 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +34 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +39 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +94 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.rb +940 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +38 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +29 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +120 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +72 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +32 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +108 -0
- data/lib/qualitysmith_extensions/filter_output.rb +107 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +151 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +32 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +119 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +69 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +113 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +34 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +118 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +16 -0
- data/lib/qualitysmith_extensions/month.rb +62 -0
- data/lib/qualitysmith_extensions/object/singleton.rb +95 -0
- data/lib/qualitysmith_extensions/simulate_input.rb +51 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +25 -0
- data/lib/qualitysmith_extensions/string/md5.rb +27 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +41 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +35 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +64 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +63 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +34 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +34 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +29 -0
- data/test/all.rb +16 -0
- metadata +94 -0
data/Readme
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
== Our Extensions Readme
|
2
|
+
|
3
|
+
== Introduction
|
4
|
+
|
5
|
+
This is a library of miscellaneous general-purpose, reusable Ruby code, quite similar in purpose and layout to {Ruby Facets}[http://facets.rubyforge.org/], but it's certainly not meant to *compete* with it!
|
6
|
+
|
7
|
+
Instead, developers are encouraged to first check if it the method or class they are looking for already exists in one of the fine existing open-source projects (like {Facets}[http://facets.rubyforge.org/] or {Extensions}[http://extensions.rubyforge.org/rdoc/index.html] or {stdlib}[http://www.ruby-doc.org/stdlib/]).
|
8
|
+
|
9
|
+
If the code you are needing hasn't already been written by someone else, then you can throw it in this library. Also submit it to an existing extensions project if you think it's any good.
|
10
|
+
|
11
|
+
Like Facets, this library contains:
|
12
|
+
* methods that add functionality to existing Ruby classes (String, Array, etc.)
|
13
|
+
* as well as new classes that aren't in core Ruby
|
14
|
+
|
15
|
+
== Installation
|
16
|
+
|
17
|
+
=== Non-gem
|
18
|
+
|
19
|
+
Install the plugin from Subversion and add an svn:external to your vendor/plugins directory with this command:
|
20
|
+
|
21
|
+
./script/plugin install -x http://code.qualitysmith.com/gemables/qualitysmith_extensions
|
22
|
+
|
23
|
+
=== Gem
|
24
|
+
|
25
|
+
In your dreams.
|
26
|
+
|
27
|
+
== Usage
|
28
|
+
|
29
|
+
=== In Rails (non-gem)
|
30
|
+
|
31
|
+
Install the plugin from Subversion and add an svn:external to your vendor/plugins directory with this command:
|
32
|
+
|
33
|
+
./script/plugin install -x http://code.qualitysmith.com/gemables/qualitysmith_extensions
|
34
|
+
|
35
|
+
Put this in your config/environment.rb :
|
36
|
+
|
37
|
+
Rails::Initializer.run do |config|
|
38
|
+
config.load_paths += %W( #{RAILS_ROOT}/vendor/plugins )
|
39
|
+
end
|
40
|
+
require "qualitysmith_extensions/lib/qualitysmith_extensions/all.rb"
|
41
|
+
|
42
|
+
=== Include as much or as little as you want
|
43
|
+
|
44
|
+
To load everything:
|
45
|
+
|
46
|
+
require "../path/to/qualitysmith_extensions/lib/qualitysmith_extensions/all.rb"
|
47
|
+
|
48
|
+
To load everything just for one class:
|
49
|
+
|
50
|
+
require "../path/to/qualitysmith_extensions/lib/qualitysmith_extensions/string/all.rb"
|
51
|
+
|
52
|
+
To load just an individual method:
|
53
|
+
|
54
|
+
require "../path/to/qualitysmith_extensions/lib/qualitysmith_extensions/array/average.rb"
|
55
|
+
|
56
|
+
=== Gem
|
57
|
+
|
58
|
+
It's not packaged as a gem yet,... but if it were, it might work something like this?:
|
59
|
+
|
60
|
+
require "rubygems"
|
61
|
+
require_gem "qualitysmith_extensions"
|
62
|
+
require "qualitysmith_extensions/lib/qualitysmith_extensions/array/all.rb"
|
63
|
+
|
64
|
+
== Running tests
|
65
|
+
|
66
|
+
Tests are self-contained within the file for the code that is under test.
|
67
|
+
|
68
|
+
To run the tests directly, you need to use the <tt>rubytest</tt> command that is included with the {Reap}[http://reap.rubyforge.org/] tool.
|
69
|
+
|
70
|
+
If you use <tt>vim</tt>, you can set up your editor to run the tests just by typing the <tt>:Test</tt> command. To set that up, just include <tt>~/svn/devscripts/vim/include.vim</tt> .
|
71
|
+
|
72
|
+
At some point in time, we may extract them into separate files using the Reap test extractor tool.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes.
|
5
|
+
# Wait, so Facets has mode (http://facets.rubyforge.org/src/doc/rdoc/core/classes/Enumerable.html#M001253) but it doesn't have mean/average?
|
6
|
+
# Whether or not this Array#average is included, Facets ought to have an Enumerable#mean/average similar to mode that uses each iterator rather than Array#size. (Still might want to keep this version if it's more efficient for Arrays?)
|
7
|
+
|
8
|
+
class Array
|
9
|
+
# Calculates the arithmetic average (mean) of the elements in the array as a <tt>Float</tt>.
|
10
|
+
# irb -> [1, 3, 3].average
|
11
|
+
# => 2.33333333333333
|
12
|
+
def average
|
13
|
+
if self.size == 0
|
14
|
+
raise ZeroDivisionError
|
15
|
+
end
|
16
|
+
self.inject(0.0) do |sum, item|
|
17
|
+
sum + item.to_f
|
18
|
+
end / self.size
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# _____ _
|
23
|
+
# |_ _|__ ___| |_
|
24
|
+
# | |/ _ \/ __| __|
|
25
|
+
# | | __/\__ \ |_
|
26
|
+
# |_|\___||___/\__|
|
27
|
+
#
|
28
|
+
=begin test
|
29
|
+
require 'test/unit'
|
30
|
+
class TheTest < Test::Unit::TestCase
|
31
|
+
def test_average
|
32
|
+
assert_equal 2, [0, 4].average
|
33
|
+
assert_equal Float, [0, 4].average.class
|
34
|
+
|
35
|
+
assert_equal 2.5, [0, 5].average
|
36
|
+
|
37
|
+
assert_raise ZeroDivisionError do
|
38
|
+
[].average
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
=end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes.
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'facets/core/kernel/silence_warnings'
|
8
|
+
|
9
|
+
class Array
|
10
|
+
# Expands (calls to_a on) all Ranges contained in this array, replacing the range with the list of elements that the range represents.
|
11
|
+
#
|
12
|
+
# [1..3, 5..7].expand_ranges
|
13
|
+
# => [1, 2, 3, 5, 6, 7]
|
14
|
+
#
|
15
|
+
def expand_ranges
|
16
|
+
new_array = []
|
17
|
+
each do |item|
|
18
|
+
silence_warnings do # Object.to_a: warning: default `to_a' will be obsolete
|
19
|
+
if item.respond_to?(:to_a)
|
20
|
+
new_array.concat item.to_a
|
21
|
+
else
|
22
|
+
new_array.concat [item]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
new_array
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# _____ _
|
31
|
+
# |_ _|__ ___| |_
|
32
|
+
# | |/ _ \/ __| __|
|
33
|
+
# | | __/\__ \ |_
|
34
|
+
# |_|\___||___/\__|
|
35
|
+
#
|
36
|
+
=begin test
|
37
|
+
require 'test/unit'
|
38
|
+
class TheTest < Test::Unit::TestCase
|
39
|
+
def test_1
|
40
|
+
assert_equal [1, 2, 3], [1, 2, 3].expand_ranges
|
41
|
+
end
|
42
|
+
def test_2
|
43
|
+
assert_equal [1, 2, 3], [1..3].expand_ranges
|
44
|
+
assert_equal [1, 2, 3, 5, 6, 7], [1..3, 5..7].expand_ranges
|
45
|
+
end
|
46
|
+
end
|
47
|
+
=end
|
48
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes
|
5
|
+
# Developer notes:
|
6
|
+
# * Name is too general? Name it something to do with 'tables'?
|
7
|
+
|
8
|
+
require 'rubygems'
|
9
|
+
require_gem 'facets'
|
10
|
+
require 'facet/array/delete_values_at'
|
11
|
+
require 'facet/array/to_hash'
|
12
|
+
class Array
|
13
|
+
|
14
|
+
=begin rdoc
|
15
|
+
Breaks an array into a hash of smaller arrays, making a new group for each unique value in the specified column. Each unique value becomes a key in the hash.
|
16
|
+
|
17
|
+
Example:
|
18
|
+
[
|
19
|
+
['a', 1],
|
20
|
+
['a', 2],
|
21
|
+
['b', 3],
|
22
|
+
['b', 4],
|
23
|
+
].group_by(0)
|
24
|
+
=>
|
25
|
+
"a"=>[[1], [2]],
|
26
|
+
"b"=>[[3], [4]]
|
27
|
+
|
28
|
+
Options:
|
29
|
+
* <tt>delete_key</tt>: deletes the key from the corresponding array if true (default true)
|
30
|
+
|
31
|
+
Example:
|
32
|
+
[
|
33
|
+
['a', 1],
|
34
|
+
['a', 2],
|
35
|
+
['b', 3],
|
36
|
+
['b', 4],
|
37
|
+
].group_by(0, :delete_key => false)
|
38
|
+
=>
|
39
|
+
"a"=>[['a', 1], ['a', 2]],
|
40
|
+
"b"=>[['b', 3], ['b', 4]]
|
41
|
+
|
42
|
+
Notes:
|
43
|
+
* <tt>self</tt> must be in the shape of a "table" (a non-sparse, rectangular, two-dimensional array).
|
44
|
+
* This is different from the GROUP BY in SQL in that it doesn't apply an aggregate (like sum or average) to each group -- it just returns each group unmodified.
|
45
|
+
|
46
|
+
=end
|
47
|
+
def group_by(column_index, *args)
|
48
|
+
options = (if args.last.is_a?(Hash) then args.pop else {} end)
|
49
|
+
hash = {}
|
50
|
+
self.each do |row|
|
51
|
+
row_to_keep = row.dup
|
52
|
+
row_to_keep.delete_values_at(column_index) unless options[:delete_key] == false
|
53
|
+
|
54
|
+
hash[row[column_index]] ||= []
|
55
|
+
hash[row[column_index]] << row_to_keep
|
56
|
+
end
|
57
|
+
hash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# _____ _
|
62
|
+
# |_ _|__ ___| |_
|
63
|
+
# | |/ _ \/ __| __|
|
64
|
+
# | | __/\__ \ |_
|
65
|
+
# |_|\___||___/\__|
|
66
|
+
#
|
67
|
+
=begin test
|
68
|
+
class TheTest < Test::Unit::TestCase
|
69
|
+
def test_group_by
|
70
|
+
assert_equal({ }, [ ].group_by(column_index = 0))
|
71
|
+
|
72
|
+
assert_equal({
|
73
|
+
"a"=>[[1], [2]],
|
74
|
+
"b"=>[[3], [4]]
|
75
|
+
}, [
|
76
|
+
['a', 1],
|
77
|
+
['a', 2],
|
78
|
+
['b', 3],
|
79
|
+
['b', 4],
|
80
|
+
].group_by(column_index = 0)
|
81
|
+
)
|
82
|
+
assert_equal({
|
83
|
+
"a"=>[['a', 1], ['a', 2]],
|
84
|
+
"b"=>[['b', 3], ['b', 4]]
|
85
|
+
}, [
|
86
|
+
['a', 1],
|
87
|
+
['a', 2],
|
88
|
+
['b', 3],
|
89
|
+
['b', 4],
|
90
|
+
].group_by(column_index = 0, :delete_key => false)
|
91
|
+
)
|
92
|
+
|
93
|
+
input = [
|
94
|
+
['Bob', "Bottle of water", 1.00],
|
95
|
+
['Bob', "Expensive stapler", 50.00],
|
96
|
+
['Alice', "Dinner for 2", 100.00],
|
97
|
+
['Alice', "Bus ride to RubyConf", 50.00],
|
98
|
+
]
|
99
|
+
assert_equal({
|
100
|
+
"Alice"=>[["Dinner for 2", 100.0], ["Bus ride to RubyConf", 50.0]],
|
101
|
+
"Bob"=>[["Bottle of water", 1.0], ["Expensive stapler", 50.0]]
|
102
|
+
}, input.group_by(column_index = 0)
|
103
|
+
)
|
104
|
+
assert_equal({
|
105
|
+
50.0=>[["Bob", "Expensive stapler"], ["Alice", "Bus ride to RubyConf"]],
|
106
|
+
100.0=>[["Alice", "Dinner for 2"]],
|
107
|
+
1.0=>[["Bob", "Bottle of water"]]
|
108
|
+
}, input.group_by(column_index = 2)
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
=end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Author:: Lance Ivy
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Not sure.
|
5
|
+
|
6
|
+
class Array
|
7
|
+
=begin rdoc
|
8
|
+
Returns the value previous to the given value. The value previous to the first is the last. Returns nil if the given value is not in the array.
|
9
|
+
|
10
|
+
Example:
|
11
|
+
sequence = ['a', 'b', 'c']
|
12
|
+
sequence.before('a') => 'c'
|
13
|
+
sequence.before('b') => 'a'
|
14
|
+
sequence.before('c') => 'b'
|
15
|
+
sequence.before('d') => nil
|
16
|
+
=end
|
17
|
+
def before(value)
|
18
|
+
return nil unless include? value
|
19
|
+
self[(index(value).to_i - 1) % length]
|
20
|
+
end
|
21
|
+
|
22
|
+
=begin rdoc
|
23
|
+
Returns the value after the given value. The value before the last is the first. Returns nil if the given value is not in the array.
|
24
|
+
|
25
|
+
Example:
|
26
|
+
sequence = ['a', 'b', 'c']
|
27
|
+
sequence.after('a') => 'b'
|
28
|
+
sequence.after('b') => 'c'
|
29
|
+
sequence.after('c') => 'a'
|
30
|
+
sequence.after('d') => nil
|
31
|
+
=end
|
32
|
+
def after(value)
|
33
|
+
return nil unless include? value
|
34
|
+
self[(index(value).to_i + 1) % length]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# _____ _
|
39
|
+
# |_ _|__ ___| |_
|
40
|
+
# | |/ _ \/ __| __|
|
41
|
+
# | | __/\__ \ |_
|
42
|
+
# |_|\___||___/\__|
|
43
|
+
#
|
44
|
+
=begin test
|
45
|
+
class TheTest < Test::Unit::TestCase
|
46
|
+
def setup
|
47
|
+
@sequence = ['a', 'b', 'c']
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_before
|
51
|
+
assert_equal 'c', @sequence.before('a')
|
52
|
+
assert_equal 'a', @sequence.before('b')
|
53
|
+
assert_equal 'b', @sequence.before('c')
|
54
|
+
assert_equal nil, @sequence.before('d')
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_after
|
58
|
+
assert_equal 'b', @sequence.after('a')
|
59
|
+
assert_equal 'c', @sequence.after('b')
|
60
|
+
assert_equal 'a', @sequence.after('c')
|
61
|
+
assert_equal nil, @sequence.after('d')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
=end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes. Symbol#to_proc -> Facets
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'extensions/symbol' unless Symbol.method_defined?(:to_proc)
|
8
|
+
require 'facets/core/kernel/require_local'
|
9
|
+
require_local '../string/shell_escape.rb'
|
10
|
+
|
11
|
+
class Array
|
12
|
+
def shell_escape
|
13
|
+
self.map(&:shell_escape)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# _____ _
|
18
|
+
# |_ _|__ ___| |_
|
19
|
+
# | |/ _ \/ __| __|
|
20
|
+
# | | __/\__ \ |_
|
21
|
+
# |_|\___||___/\__|
|
22
|
+
#
|
23
|
+
=begin test
|
24
|
+
require 'test/unit'
|
25
|
+
class TheTest < Test::Unit::TestCase
|
26
|
+
def test_1
|
27
|
+
assert_equal ['a'], ['a'].shell_escape
|
28
|
+
end
|
29
|
+
def test_2
|
30
|
+
assert_equal ["arg1", "'multiple words for single argument'"],
|
31
|
+
['arg1', 'multiple words for single argument'].shell_escape
|
32
|
+
end
|
33
|
+
end
|
34
|
+
=end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Author:: Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes.
|
5
|
+
|
6
|
+
class Array
|
7
|
+
|
8
|
+
# A lot like array.flatten, except that it will also "flatten" ranges (by converting range to range.to_a) and any other objects that respond to to_a contained in the array in addition to arrays contained in the array.
|
9
|
+
# Compare with Array#expand_ranges
|
10
|
+
def to_a_recursive
|
11
|
+
map do |item|
|
12
|
+
# Assume that all arrays contain only elements that do not respond to to_a_recursive or arrays.
|
13
|
+
if item.respond_to? :to_a_recursive
|
14
|
+
item.to_a_recursive
|
15
|
+
else
|
16
|
+
item.to_a
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# _____ _
|
23
|
+
# |_ _|__ ___| |_
|
24
|
+
# | |/ _ \/ __| __|
|
25
|
+
# | | __/\__ \ |_
|
26
|
+
# |_|\___||___/\__|
|
27
|
+
#
|
28
|
+
=begin test
|
29
|
+
require 'test/unit'
|
30
|
+
class TheTest < Test::Unit::TestCase
|
31
|
+
def test_1
|
32
|
+
assert_equal [[1, 2, 3], [5, 6, 7]], [1..3, 5..7].to_a_recursive
|
33
|
+
end
|
34
|
+
def test_2
|
35
|
+
assert_equal [[1, 2, 3], [ [5, 6, 7], [9, 10] ] ], [1..3, [5..7, 9..10]].to_a_recursive
|
36
|
+
end
|
37
|
+
end
|
38
|
+
=end
|
39
|
+
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# Author:: Anthony Kaufman, Tyler Rick
|
2
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
3
|
+
# License:: Ruby License
|
4
|
+
# Submit to Facets?:: Yes.
|
5
|
+
|
6
|
+
autoload :CGI, 'cgi'
|
7
|
+
class Array
|
8
|
+
|
9
|
+
=begin rdoc
|
10
|
+
Converts into a string that can be used as the {query string}[http://en.wikipedia.org/wiki/Query_string] of a URL (for example, <tt>?key[]=val1&key[]=val2</tt>).
|
11
|
+
|
12
|
+
Example:
|
13
|
+
[
|
14
|
+
'Fred',
|
15
|
+
'Sam'
|
16
|
+
].to_query_string('names')
|
17
|
+
==> "names[]=Fred&names[]=Sam"
|
18
|
+
|
19
|
+
<tt>key</tt> is the name of the key in params that will receive the array when you load the page. So, for example, if you go to page with this query string (key = "names"): <tt>?names[]=Fred&names[]=Sam</tt>, params will be have a key "names", like so: <tt>{"names"=>["Fred", "Sam"]}</tt>.
|
20
|
+
=end
|
21
|
+
def to_query_string(key)
|
22
|
+
elements = []
|
23
|
+
|
24
|
+
self.each do |value|
|
25
|
+
_key = key + '[]'
|
26
|
+
if value.is_a? Array
|
27
|
+
raise "Array#to_query_string only works on flat (1-dimensional) arrays."
|
28
|
+
elsif value.respond_to? :to_query_string
|
29
|
+
value = value.to_query_string(_key)
|
30
|
+
else
|
31
|
+
value = CGI.escape value.to_s
|
32
|
+
end
|
33
|
+
elements << _key + '=' + value
|
34
|
+
end
|
35
|
+
|
36
|
+
elements.join('&')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# _____ _
|
41
|
+
# |_ _|__ ___| |_
|
42
|
+
# | |/ _ \/ __| __|
|
43
|
+
# | | __/\__ \ |_
|
44
|
+
# |_|\___||___/\__|
|
45
|
+
#
|
46
|
+
=begin test
|
47
|
+
class TheTest < Test::Unit::TestCase
|
48
|
+
#-------------------------------------------------------------------------------------------------
|
49
|
+
# Array:
|
50
|
+
|
51
|
+
def test_array_to_query_string_trivial
|
52
|
+
data = []
|
53
|
+
assert_equal '', data.to_query_string('names')
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_array_to_query_string_basic
|
57
|
+
data = [
|
58
|
+
'Fred',
|
59
|
+
'Sam'
|
60
|
+
]
|
61
|
+
assert_equal 'names[]=Fred&names[]=Sam', data.to_query_string('names')
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_array_to_query_string_encoding
|
65
|
+
data = ['f&r', 'a w$']
|
66
|
+
|
67
|
+
assert_equal 'foo[]=f%26r&foo[]=a+w%24', data.to_query_string('foo')
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_array_to_query_string_nesting
|
71
|
+
data = [
|
72
|
+
[
|
73
|
+
'Wilma',
|
74
|
+
'Sara'
|
75
|
+
],
|
76
|
+
[
|
77
|
+
'Fred',
|
78
|
+
'Sam'
|
79
|
+
]
|
80
|
+
]
|
81
|
+
assert_raise RuntimeError do data.to_query_string('names') end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
=end
|
85
|
+
|
86
|
+
=begin examples
|
87
|
+
require 'irb/xmp'
|
88
|
+
xmp <<End
|
89
|
+
[
|
90
|
+
'Fred',
|
91
|
+
'Sam'
|
92
|
+
].to_query_string('names')
|
93
|
+
End
|
94
|
+
=end
|