extlib 0.9.8 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of extlib might be problematic. Click here for more details.

Files changed (54) hide show
  1. data/History.txt +22 -0
  2. data/LICENSE +1 -1
  3. data/README +0 -0
  4. data/Rakefile +17 -12
  5. data/lib/extlib.rb +1 -1
  6. data/lib/extlib/blank.rb +51 -21
  7. data/lib/extlib/boolean.rb +1 -1
  8. data/lib/extlib/class.rb +12 -12
  9. data/lib/extlib/datetime.rb +20 -2
  10. data/lib/extlib/dictionary.rb +2 -2
  11. data/lib/extlib/hash.rb +57 -34
  12. data/lib/extlib/inflection.rb +0 -1
  13. data/lib/extlib/lazy_array.rb +327 -36
  14. data/lib/extlib/logger.rb +8 -8
  15. data/lib/extlib/mash.rb +45 -45
  16. data/lib/extlib/module.rb +1 -1
  17. data/lib/extlib/nil.rb +1 -1
  18. data/lib/extlib/numeric.rb +1 -1
  19. data/lib/extlib/object.rb +8 -21
  20. data/lib/extlib/object_space.rb +3 -3
  21. data/lib/extlib/pathname.rb +10 -0
  22. data/lib/extlib/pooling.rb +9 -17
  23. data/lib/extlib/rubygems.rb +7 -7
  24. data/lib/extlib/simple_set.rb +35 -8
  25. data/lib/extlib/string.rb +85 -42
  26. data/lib/extlib/struct.rb +10 -1
  27. data/lib/extlib/symbol.rb +11 -7
  28. data/lib/extlib/time.rb +31 -9
  29. data/lib/extlib/version.rb +1 -1
  30. data/lib/extlib/virtual_file.rb +1 -1
  31. data/spec/blank_spec.rb +85 -0
  32. data/spec/class_spec.rb +141 -0
  33. data/spec/datetime_spec.rb +22 -0
  34. data/spec/hash_spec.rb +537 -0
  35. data/spec/hook_spec.rb +1198 -0
  36. data/spec/inflection/plural_spec.rb +564 -0
  37. data/spec/inflection/singular_spec.rb +497 -0
  38. data/spec/inflection_extras_spec.rb +93 -0
  39. data/spec/lazy_array_spec.rb +1869 -0
  40. data/spec/mash_spec.rb +286 -0
  41. data/spec/module_spec.rb +58 -0
  42. data/spec/object_space_spec.rb +9 -0
  43. data/spec/object_spec.rb +114 -0
  44. data/spec/pooling_spec.rb +499 -0
  45. data/spec/simple_set_spec.rb +57 -0
  46. data/spec/spec_helper.rb +7 -0
  47. data/spec/string_spec.rb +220 -0
  48. data/spec/struct_spec.rb +12 -0
  49. data/spec/symbol_spec.rb +8 -0
  50. data/spec/time_spec.rb +22 -0
  51. data/spec/try_dup_spec.rb +45 -0
  52. data/spec/virtual_file_spec.rb +21 -0
  53. metadata +51 -26
  54. data/README.txt +0 -3
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'json'
3
+
4
+ describe DateTime, "#to_time" do
5
+ before do
6
+ @expected = Time.now.to_s
7
+ @datetime = DateTime.parse(@expected)
8
+ end
9
+
10
+ it "should return a copy of time" do
11
+ time = @datetime.to_time
12
+ time.class.should == Time
13
+ time.to_s.should == @expected
14
+ end
15
+ end
16
+
17
+ describe Time, "#to_datetime" do
18
+ it "should return a copy of its self" do
19
+ datetime = DateTime.now
20
+ datetime.to_datetime.should == datetime
21
+ end
22
+ end
@@ -0,0 +1,537 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require "date"
3
+ require 'bigdecimal'
4
+
5
+ describe Hash, "environmentize_keys!" do
6
+ it "should transform keys to uppercase text" do
7
+ { :test_1 => 'test', 'test_2' => 'test', 1 => 'test' }.environmentize_keys!.should ==
8
+ { 'TEST_1' => 'test', 'TEST_2' => 'test', '1' => 'test' }
9
+ end
10
+
11
+ it "should only transform one level of keys" do
12
+ { :test_1 => { :test2 => 'test'} }.environmentize_keys!.should ==
13
+ { 'TEST_1' => { :test2 => 'test'} }
14
+ end
15
+ end
16
+
17
+
18
+ describe Hash, "only" do
19
+ before do
20
+ @hash = { :one => 'ONE', 'two' => 'TWO', 3 => 'THREE', 4 => nil }
21
+ end
22
+
23
+ it "should return a hash with only the given key(s)" do
24
+ @hash.only(:not_in_there).should == {}
25
+ @hash.only(4).should == {4 => nil}
26
+ @hash.only(:one).should == { :one => 'ONE' }
27
+ @hash.only(:one, 3).should == { :one => 'ONE', 3 => 'THREE' }
28
+ end
29
+ end
30
+
31
+
32
+ describe Hash, "except" do
33
+ before do
34
+ @hash = { :one => 'ONE', 'two' => 'TWO', 3 => 'THREE' }
35
+ end
36
+
37
+ it "should return a hash without only the given key(s)" do
38
+ @hash.except(:one).should == { 'two' => 'TWO', 3 => 'THREE' }
39
+ @hash.except(:one, 3).should == { 'two' => 'TWO' }
40
+ end
41
+ end
42
+
43
+
44
+ describe Hash, "to_xml_attributes" do
45
+ before do
46
+ @hash = { :one => "ONE", "two" => "TWO" }
47
+ end
48
+
49
+ it "should turn the hash into xml attributes" do
50
+ attrs = @hash.to_xml_attributes
51
+ attrs.should match(/one="ONE"/m)
52
+ attrs.should match(/two="TWO"/m)
53
+ end
54
+
55
+ it 'should preserve _ in hash keys' do
56
+ attrs = {
57
+ :some_long_attribute => "with short value",
58
+ :crash => :burn,
59
+ :merb => "uses extlib"
60
+ }.to_xml_attributes
61
+
62
+ attrs.should =~ /some_long_attribute="with short value"/
63
+ attrs.should =~ /merb="uses extlib"/
64
+ attrs.should =~ /crash="burn"/
65
+ end
66
+ end
67
+
68
+
69
+ describe Hash, "from_xml" do
70
+ it "should transform a simple tag with content" do
71
+ xml = "<tag>This is the contents</tag>"
72
+ Hash.from_xml(xml).should == { 'tag' => 'This is the contents' }
73
+ end
74
+
75
+ it "should work with cdata tags" do
76
+ xml = <<-END
77
+ <tag>
78
+ <![CDATA[
79
+ text inside cdata
80
+ ]]>
81
+ </tag>
82
+ END
83
+ Hash.from_xml(xml)["tag"].strip.should == "text inside cdata"
84
+ end
85
+
86
+ it "should transform a simple tag with attributes" do
87
+ xml = "<tag attr1='1' attr2='2'></tag>"
88
+ hash = { 'tag' => { 'attr1' => '1', 'attr2' => '2' } }
89
+ Hash.from_xml(xml).should == hash
90
+ end
91
+
92
+ it "should transform repeating siblings into an array" do
93
+ xml =<<-XML
94
+ <opt>
95
+ <user login="grep" fullname="Gary R Epstein" />
96
+ <user login="stty" fullname="Simon T Tyson" />
97
+ </opt>
98
+ XML
99
+
100
+ Hash.from_xml(xml)['opt']['user'].should be_an_instance_of(Array)
101
+
102
+ hash = {
103
+ 'opt' => {
104
+ 'user' => [{
105
+ 'login' => 'grep',
106
+ 'fullname' => 'Gary R Epstein'
107
+ },{
108
+ 'login' => 'stty',
109
+ 'fullname' => 'Simon T Tyson'
110
+ }]
111
+ }
112
+ }
113
+
114
+ Hash.from_xml(xml).should == hash
115
+ end
116
+
117
+ it "should not transform non-repeating siblings into an array" do
118
+ xml =<<-XML
119
+ <opt>
120
+ <user login="grep" fullname="Gary R Epstein" />
121
+ </opt>
122
+ XML
123
+
124
+ Hash.from_xml(xml)['opt']['user'].should be_an_instance_of(Hash)
125
+
126
+ hash = {
127
+ 'opt' => {
128
+ 'user' => {
129
+ 'login' => 'grep',
130
+ 'fullname' => 'Gary R Epstein'
131
+ }
132
+ }
133
+ }
134
+
135
+ Hash.from_xml(xml).should == hash
136
+ end
137
+
138
+ it "should typecast an integer" do
139
+ xml = "<tag type='integer'>10</tag>"
140
+ Hash.from_xml(xml)['tag'].should == 10
141
+ end
142
+
143
+ it "should typecast a true boolean" do
144
+ xml = "<tag type='boolean'>true</tag>"
145
+ Hash.from_xml(xml)['tag'].should be_true
146
+ end
147
+
148
+ it "should typecast a false boolean" do
149
+ ["false"].each do |w|
150
+ Hash.from_xml("<tag type='boolean'>#{w}</tag>")['tag'].should be_false
151
+ end
152
+ end
153
+
154
+ it "should typecast a datetime" do
155
+ xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
156
+ Hash.from_xml(xml)['tag'].should == Time.parse( '2007-12-31 10:32' ).utc
157
+ end
158
+
159
+ it "should typecast a date" do
160
+ xml = "<tag type='date'>2007-12-31</tag>"
161
+ Hash.from_xml(xml)['tag'].should == Date.parse('2007-12-31')
162
+ end
163
+
164
+ it "should unescape html entities" do
165
+ values = {
166
+ "<" => "&lt;",
167
+ ">" => "&gt;",
168
+ '"' => "&quot;",
169
+ "'" => "&apos;",
170
+ "&" => "&amp;"
171
+ }
172
+ values.each do |k,v|
173
+ xml = "<tag>Some content #{v}</tag>"
174
+ Hash.from_xml(xml)['tag'].should match(Regexp.new(k))
175
+ end
176
+ end
177
+
178
+ it "should undasherize keys as tags" do
179
+ xml = "<tag-1>Stuff</tag-1>"
180
+ Hash.from_xml(xml).keys.should include( 'tag_1' )
181
+ end
182
+
183
+ it "should undasherize keys as attributes" do
184
+ xml = "<tag1 attr-1='1'></tag1>"
185
+ Hash.from_xml(xml)['tag1'].keys.should include( 'attr_1')
186
+ end
187
+
188
+ it "should undasherize keys as tags and attributes" do
189
+ xml = "<tag-1 attr-1='1'></tag-1>"
190
+ Hash.from_xml(xml).keys.should include( 'tag_1' )
191
+ Hash.from_xml(xml)['tag_1'].keys.should include( 'attr_1')
192
+ end
193
+
194
+ it "should render nested content correctly" do
195
+ xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
196
+ Hash.from_xml(xml)['root']['tag1'].should == "Tag1 Content <em><strong>This is strong</strong></em>"
197
+ end
198
+
199
+ it "should render nested content with split text nodes correctly" do
200
+ xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
201
+ Hash.from_xml(xml)['root'].should == "Tag1 Content<em>Stuff</em> Hi There"
202
+ end
203
+
204
+ it "should ignore attributes when a child is a text node" do
205
+ xml = "<root attr1='1'>Stuff</root>"
206
+ Hash.from_xml(xml).should == { "root" => "Stuff" }
207
+ end
208
+
209
+ it "should ignore attributes when any child is a text node" do
210
+ xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
211
+ Hash.from_xml(xml).should == { "root" => "Stuff <em>in italics</em>" }
212
+ end
213
+
214
+ it "should correctly transform multiple children" do
215
+ xml = <<-XML
216
+ <user gender='m'>
217
+ <age type='integer'>35</age>
218
+ <name>Home Simpson</name>
219
+ <dob type='date'>1988-01-01</dob>
220
+ <joined-at type='datetime'>2000-04-28 23:01</joined-at>
221
+ <is-cool type='boolean'>true</is-cool>
222
+ </user>
223
+ XML
224
+
225
+ hash = {
226
+ "user" => {
227
+ "gender" => "m",
228
+ "age" => 35,
229
+ "name" => "Home Simpson",
230
+ "dob" => Date.parse('1988-01-01'),
231
+ "joined_at" => Time.parse("2000-04-28 23:01"),
232
+ "is_cool" => true
233
+ }
234
+ }
235
+
236
+ Hash.from_xml(xml).should == hash
237
+ end
238
+
239
+ it "should properly handle nil values (ActiveSupport Compatible)" do
240
+ topic_xml = <<-EOT
241
+ <topic>
242
+ <title></title>
243
+ <id type="integer"></id>
244
+ <approved type="boolean"></approved>
245
+ <written-on type="date"></written-on>
246
+ <viewed-at type="datetime"></viewed-at>
247
+ <content type="yaml"></content>
248
+ <parent-id></parent-id>
249
+ </topic>
250
+ EOT
251
+
252
+ expected_topic_hash = {
253
+ 'title' => nil,
254
+ 'id' => nil,
255
+ 'approved' => nil,
256
+ 'written_on' => nil,
257
+ 'viewed_at' => nil,
258
+ 'content' => nil,
259
+ 'parent_id' => nil
260
+ }
261
+ Hash.from_xml(topic_xml)["topic"].should == expected_topic_hash
262
+ end
263
+
264
+ it "should handle a single record from xml (ActiveSupport Compatible)" do
265
+ topic_xml = <<-EOT
266
+ <topic>
267
+ <title>The First Topic</title>
268
+ <author-name>David</author-name>
269
+ <id type="integer">1</id>
270
+ <approved type="boolean"> true </approved>
271
+ <replies-count type="integer">0</replies-count>
272
+ <replies-close-in type="integer">2592000000</replies-close-in>
273
+ <written-on type="date">2003-07-16</written-on>
274
+ <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
275
+ <content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</content>
276
+ <author-email-address>david@loudthinking.com</author-email-address>
277
+ <parent-id></parent-id>
278
+ <ad-revenue type="decimal">1.5</ad-revenue>
279
+ <optimum-viewing-angle type="float">135</optimum-viewing-angle>
280
+ <resident type="symbol">yes</resident>
281
+ </topic>
282
+ EOT
283
+
284
+ expected_topic_hash = {
285
+ 'title' => "The First Topic",
286
+ 'author_name' => "David",
287
+ 'id' => 1,
288
+ 'approved' => true,
289
+ 'replies_count' => 0,
290
+ 'replies_close_in' => 2592000000,
291
+ 'written_on' => Date.new(2003, 7, 16),
292
+ 'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
293
+ # Changed this line where the key is :message. The yaml specifies this as a symbol, and who am I to change what you specify
294
+ # The line in ActiveSupport is
295
+ # 'content' => { 'message' => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
296
+ 'content' => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
297
+ 'author_email_address' => "david@loudthinking.com",
298
+ 'parent_id' => nil,
299
+ 'ad_revenue' => BigDecimal("1.50"),
300
+ 'optimum_viewing_angle' => 135.0,
301
+ 'resident' => :yes
302
+ }
303
+
304
+ Hash.from_xml(topic_xml)["topic"].each do |k,v|
305
+ v.should == expected_topic_hash[k]
306
+ end
307
+ end
308
+
309
+ it "should handle multiple records (ActiveSupport Compatible)" do
310
+ topics_xml = <<-EOT
311
+ <topics type="array">
312
+ <topic>
313
+ <title>The First Topic</title>
314
+ <author-name>David</author-name>
315
+ <id type="integer">1</id>
316
+ <approved type="boolean">false</approved>
317
+ <replies-count type="integer">0</replies-count>
318
+ <replies-close-in type="integer">2592000000</replies-close-in>
319
+ <written-on type="date">2003-07-16</written-on>
320
+ <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
321
+ <content>Have a nice day</content>
322
+ <author-email-address>david@loudthinking.com</author-email-address>
323
+ <parent-id nil="true"></parent-id>
324
+ </topic>
325
+ <topic>
326
+ <title>The Second Topic</title>
327
+ <author-name>Jason</author-name>
328
+ <id type="integer">1</id>
329
+ <approved type="boolean">false</approved>
330
+ <replies-count type="integer">0</replies-count>
331
+ <replies-close-in type="integer">2592000000</replies-close-in>
332
+ <written-on type="date">2003-07-16</written-on>
333
+ <viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
334
+ <content>Have a nice day</content>
335
+ <author-email-address>david@loudthinking.com</author-email-address>
336
+ <parent-id></parent-id>
337
+ </topic>
338
+ </topics>
339
+ EOT
340
+
341
+ expected_topic_hash = {
342
+ 'title' => "The First Topic",
343
+ 'author_name' => "David",
344
+ 'id' => 1,
345
+ 'approved' => false,
346
+ 'replies_count' => 0,
347
+ 'replies_close_in' => 2592000000,
348
+ 'written_on' => Date.new(2003, 7, 16),
349
+ 'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
350
+ 'content' => "Have a nice day",
351
+ 'author_email_address' => "david@loudthinking.com",
352
+ 'parent_id' => nil
353
+ }
354
+ # puts Hash.from_xml(topics_xml)['topics'].first.inspect
355
+ Hash.from_xml(topics_xml)["topics"].first.each do |k,v|
356
+ v.should == expected_topic_hash[k]
357
+ end
358
+ end
359
+
360
+ it "should handle a single record from_xml with attributes other than type (ActiveSupport Compatible)" do
361
+ topic_xml = <<-EOT
362
+ <rsp stat="ok">
363
+ <photos page="1" pages="1" perpage="100" total="16">
364
+ <photo id="175756086" owner="55569174@N00" secret="0279bf37a1" server="76" title="Colored Pencil PhotoBooth Fun" ispublic="1" isfriend="0" isfamily="0"/>
365
+ </photos>
366
+ </rsp>
367
+ EOT
368
+
369
+ expected_topic_hash = {
370
+ 'id' => "175756086",
371
+ 'owner' => "55569174@N00",
372
+ 'secret' => "0279bf37a1",
373
+ 'server' => "76",
374
+ 'title' => "Colored Pencil PhotoBooth Fun",
375
+ 'ispublic' => "1",
376
+ 'isfriend' => "0",
377
+ 'isfamily' => "0",
378
+ }
379
+ Hash.from_xml(topic_xml)["rsp"]["photos"]["photo"].each do |k,v|
380
+ v.should == expected_topic_hash[k]
381
+ end
382
+ end
383
+
384
+ it "should handle an emtpy array (ActiveSupport Compatible)" do
385
+ blog_xml = <<-XML
386
+ <blog>
387
+ <posts type="array"></posts>
388
+ </blog>
389
+ XML
390
+ expected_blog_hash = {"blog" => {"posts" => []}}
391
+ Hash.from_xml(blog_xml).should == expected_blog_hash
392
+ end
393
+
394
+ it "should handle empty array with whitespace from xml (ActiveSupport Compatible)" do
395
+ blog_xml = <<-XML
396
+ <blog>
397
+ <posts type="array">
398
+ </posts>
399
+ </blog>
400
+ XML
401
+ expected_blog_hash = {"blog" => {"posts" => []}}
402
+ Hash.from_xml(blog_xml).should == expected_blog_hash
403
+ end
404
+
405
+ it "should handle array with one entry from_xml (ActiveSupport Compatible)" do
406
+ blog_xml = <<-XML
407
+ <blog>
408
+ <posts type="array">
409
+ <post>a post</post>
410
+ </posts>
411
+ </blog>
412
+ XML
413
+ expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
414
+ Hash.from_xml(blog_xml).should == expected_blog_hash
415
+ end
416
+
417
+ it "should handle array with multiple entries from xml (ActiveSupport Compatible)" do
418
+ blog_xml = <<-XML
419
+ <blog>
420
+ <posts type="array">
421
+ <post>a post</post>
422
+ <post>another post</post>
423
+ </posts>
424
+ </blog>
425
+ XML
426
+ expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
427
+ Hash.from_xml(blog_xml).should == expected_blog_hash
428
+ end
429
+
430
+ it "should handle file types (ActiveSupport Compatible)" do
431
+ blog_xml = <<-XML
432
+ <blog>
433
+ <logo type="file" name="logo.png" content_type="image/png">
434
+ </logo>
435
+ </blog>
436
+ XML
437
+ hash = Hash.from_xml(blog_xml)
438
+ hash.should have_key('blog')
439
+ hash['blog'].should have_key('logo')
440
+
441
+ file = hash['blog']['logo']
442
+ file.original_filename.should == 'logo.png'
443
+ file.content_type.should == 'image/png'
444
+ end
445
+
446
+ it "should handle file from xml with defaults (ActiveSupport Compatible)" do
447
+ blog_xml = <<-XML
448
+ <blog>
449
+ <logo type="file">
450
+ </logo>
451
+ </blog>
452
+ XML
453
+ file = Hash.from_xml(blog_xml)['blog']['logo']
454
+ file.original_filename.should == 'untitled'
455
+ file.content_type.should == 'application/octet-stream'
456
+ end
457
+
458
+ it "should handle xsd like types from xml (ActiveSupport Compatible)" do
459
+ bacon_xml = <<-EOT
460
+ <bacon>
461
+ <weight type="double">0.5</weight>
462
+ <price type="decimal">12.50</price>
463
+ <chunky type="boolean"> 1 </chunky>
464
+ <expires-at type="dateTime">2007-12-25T12:34:56+0000</expires-at>
465
+ <notes type="string"></notes>
466
+ <illustration type="base64Binary">YmFiZS5wbmc=</illustration>
467
+ </bacon>
468
+ EOT
469
+
470
+ expected_bacon_hash = {
471
+ 'weight' => 0.5,
472
+ 'chunky' => true,
473
+ 'price' => BigDecimal("12.50"),
474
+ 'expires_at' => Time.utc(2007,12,25,12,34,56),
475
+ 'notes' => "",
476
+ 'illustration' => "babe.png"
477
+ }
478
+
479
+ Hash.from_xml(bacon_xml)["bacon"].should == expected_bacon_hash
480
+ end
481
+
482
+ it "should let type trickle through when unknown (ActiveSupport Compatible)" do
483
+ product_xml = <<-EOT
484
+ <product>
485
+ <weight type="double">0.5</weight>
486
+ <image type="ProductImage"><filename>image.gif</filename></image>
487
+
488
+ </product>
489
+ EOT
490
+
491
+ expected_product_hash = {
492
+ 'weight' => 0.5,
493
+ 'image' => {'type' => 'ProductImage', 'filename' => 'image.gif' },
494
+ }
495
+
496
+ Hash.from_xml(product_xml)["product"].should == expected_product_hash
497
+ end
498
+
499
+ it "should handle unescaping from xml (ActiveResource Compatible)" do
500
+ xml_string = '<person><bare-string>First &amp; Last Name</bare-string><pre-escaped-string>First &amp;amp; Last Name</pre-escaped-string></person>'
501
+ expected_hash = {
502
+ 'bare_string' => 'First & Last Name',
503
+ 'pre_escaped_string' => 'First &amp; Last Name'
504
+ }
505
+
506
+ Hash.from_xml(xml_string)['person'].should == expected_hash
507
+ end
508
+ end
509
+
510
+ describe Hash, 'to_params' do
511
+ {
512
+ { "foo" => "bar", "baz" => "bat" } => "foo=bar&baz=bat",
513
+ { "foo" => [ "bar", "baz" ] } => "foo[]=bar&foo[]=baz",
514
+ { "foo" => [ {"bar" => "1"}, {"bar" => 2} ] } => "foo[][bar]=1&foo[][bar]=2",
515
+ { "foo" => { "bar" => [ {"baz" => 1}, {"baz" => "2"} ] } } => "foo[bar][][baz]=1&foo[bar][][baz]=2",
516
+ { "foo" => {"1" => "bar", "2" => "baz"} } => "foo[1]=bar&foo[2]=baz"
517
+ }.each do |hash, params|
518
+ it "should covert hash: #{hash.inspect} to params: #{params.inspect}" do
519
+ hash.to_params.split('&').sort.should == params.split('&').sort
520
+ end
521
+ end
522
+
523
+ it 'should not leave a trailing &' do
524
+ { :name => 'Bob', :address => { :street => '111 Ruby Ave.', :city => 'Ruby Central', :phones => ['111-111-1111', '222-222-2222'] } }.to_params.should_not match(/&$/)
525
+ end
526
+ end
527
+
528
+ describe Hash, 'to_mash' do
529
+ before :each do
530
+ @hash = Hash.new(10)
531
+ end
532
+
533
+ it "copies default Hash value to Mash" do
534
+ @mash = @hash.to_mash
535
+ @mash[:merb].should == 10
536
+ end
537
+ end