Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #7421: hash.3.diff

File hash.3.diff, 5.3 kB (added by mislav, 2 years ago)

final, merged with other related patches

  • test/unit/hash.html

    old new  
    4646    multiple_nil:     { color: ['r', null, 'g', undefined, 0] }, 
    4747    multiple_all_nil: { color: [null, undefined] }, 
    4848    multiple_empty:   { color: [] }, 
     49    multiple_special: { 'stuff[]': $w('$ a ;') }, 
    4950 
    5051    value_undefined:  { a:"b", c:undefined }, 
    5152    value_null:       { a:"b", c:null }, 
     
    6364   
    6465  new Test.Unit.Runner({ 
    6566     
     67    testConstruct: function(){ with(this) { 
     68      var h = $H(Fixtures.one) 
     69      assertNotIdentical(Fixtures.one, h) 
     70      assertIdentical(h, $H(h)) 
     71 
     72      var h2 = new Hash(h) 
     73      assertNotIdentical(h, h2) 
     74      assertEqual(h.inspect(), h2.inspect()) 
     75    }}, 
     76     
    6677    testKeys: function(){ with(this) { 
    6778      assertEnumEqual([],               $H({}).keys()); 
    6879      assertEnumEqual(['a'],            $H(Fixtures.one).keys()); 
     
    96107      assertEqual('',                        $H({}).toQueryString()); 
    97108      assertEqual('a=A%23',                  $H(Fixtures.one).toQueryString()); 
    98109      assertEqual('a=A&b=B&c=C&d=D%23',      $H(Fixtures.many).toQueryString()); 
    99       assertEqual("a=b&c=",                  $H(Fixtures.value_undefined).toQueryString()); 
    100       assertEqual("a=b&c=",                  $H(Fixtures.value_null).toQueryString()); 
     110      assertEqual("a=b",                     $H(Fixtures.value_undefined).toQueryString()); 
     111      assertEqual("a=b",                     $H(Fixtures.value_null).toQueryString()); 
    101112      assertEqual("a=b&c=0",                 $H(Fixtures.value_zero).toQueryString()); 
    102113      assertEqual("color=r&color=g&color=b", $H(Fixtures.multiple).toQueryString()); 
    103114      assertEqual("color=r&color=g&color=0", $H(Fixtures.multiple_nil).toQueryString()); 
    104       assertEqual("color=",                  $H(Fixtures.multiple_all_nil).toQueryString()); 
    105       assertEqual("color=",                  $H(Fixtures.multiple_empty).toQueryString()); 
    106        
    107       assertEqual("_each=E&map=M&keys=K&values=V&collect=C&inject=I", Hash.toQueryString(Fixtures.dangerous)); 
     115      assertEqual("",                        $H(Fixtures.multiple_all_nil).toQueryString()); 
     116      assertEqual("",                        $H(Fixtures.multiple_empty).toQueryString()); 
     117      assertEqual("stuff%5B%5D=%24&stuff%5B%5D=a&stuff%5B%5D=%3B", $H(Fixtures.multiple_special).toQueryString()); 
     118 
     119      assertEnumEqual($w("_each=E map=M keys=K values=V collect=C inject=I").sort(), 
     120        Hash.toQueryString(Fixtures.dangerous).split('&').sort()); 
     121      assertEnumEqual($w('_each=E map=M keys=K values=V collect=C inject=I').sort(), 
     122        $H(Fixtures.dangerous).toQueryString().split('&').sort()); 
    108123    }}, 
    109124     
    110125    testInspect: function(){ with(this) { 
  • src/hash.js

    old new  
    1 var Hash = function(obj) { 
    2   Object.extend(this, obj || {}); 
     1var Hash = function(object) { 
     2  if (object instanceof Hash) this.merge(object); 
     3  else Object.extend(this, object || {}); 
    34}; 
    45 
    56Object.extend(Hash, { 
    67  toQueryString: function(obj) { 
    78    var parts = []; 
     9    parts.add = arguments.callee.addPair; 
    810     
    9          this.prototype._each.call(obj, function(pair) { 
     11    this.prototype._each.call(obj, function(pair) { 
    1012      if (!pair.key) return; 
     13      var value = pair.value; 
    1114       
    12       if (pair.value && pair.value.constructor == Array) { 
    13         var values = pair.value.compact(); 
    14         if (values.length < 2) pair.value = values.reduce(); 
    15         else { 
    16                 key = encodeURIComponent(pair.key); 
    17           values.each(function(value) { 
    18             value = value != undefined ? encodeURIComponent(value) : ''; 
    19             parts.push(key + '=' + encodeURIComponent(value)); 
    20           }); 
    21           return; 
    22         } 
     15      if (value && typeof value == 'object') { 
     16        if (value.constructor == Array) value.each(function(value) { 
     17          parts.add(pair.key, value); 
     18        }); 
     19        return; 
    2320      } 
    24       if (pair.value == undefined) pair[1] = ''; 
    25       parts.push(pair.map(encodeURIComponent).join('=')); 
    26           }); 
     21      parts.add(pair.key, value); 
     22    }); 
    2723     
    2824    return parts.join('&'); 
    2925  } 
    3026}); 
    3127 
     28Hash.toQueryString.addPair = function(key, value, prefix) { 
     29  if (value == null) return; 
     30  key = encodeURIComponent(key); 
     31  this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); 
     32} 
     33 
    3234Object.extend(Hash.prototype, Enumerable); 
    3335Object.extend(Hash.prototype, { 
    3436  _each: function(iterator) { 
     
    8688}); 
    8789 
    8890function $H(object) { 
    89   if (object && object.constructor == Hash) return object; 
     91  if (object instanceof Hash) return object; 
    9092  return new Hash(object); 
    9193}; 
     94 
     95// Safari iterates over shadowed properties 
     96if (function() { 
     97  var i = 0, Test = function(value) { this.key = value }; 
     98  Test.prototype.key = 'foo'; 
     99  for (var property in new Test('bar')) i++; 
     100  return i > 1; 
     101}()) Hash.prototype._each = function(iterator) { 
     102  var cache = []; 
     103  for (var key in this) { 
     104    var value = this[key]; 
     105    if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; 
     106    cache.push(key); 
     107    var pair = [key, value]; 
     108    pair.key = key; 
     109    pair.value = value; 
     110    iterator(pair); 
     111  } 
     112};