backbone-rails 0.5.3.1 → 0.9.0
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.
- data/vendor/assets/javascripts/backbone.js +477 -379
- data/vendor/assets/javascripts/json2.js +27 -20
- data/vendor/assets/javascripts/underscore.js +81 -59
- metadata +5 -5
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
http://www.JSON.org/json2.js
|
3
|
-
2011-
|
3
|
+
2011-10-19
|
4
4
|
|
5
5
|
Public Domain.
|
6
6
|
|
@@ -146,7 +146,7 @@
|
|
146
146
|
redistribute.
|
147
147
|
*/
|
148
148
|
|
149
|
-
/*jslint evil: true,
|
149
|
+
/*jslint evil: true, regexp: true */
|
150
150
|
|
151
151
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
152
152
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
@@ -165,7 +165,7 @@ if (!JSON) {
|
|
165
165
|
}
|
166
166
|
|
167
167
|
(function () {
|
168
|
-
|
168
|
+
'use strict';
|
169
169
|
|
170
170
|
function f(n) {
|
171
171
|
// Format integers to have at least two digits.
|
@@ -176,13 +176,14 @@ if (!JSON) {
|
|
176
176
|
|
177
177
|
Date.prototype.toJSON = function (key) {
|
178
178
|
|
179
|
-
return isFinite(this.valueOf())
|
180
|
-
this.getUTCFullYear() + '-' +
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
179
|
+
return isFinite(this.valueOf())
|
180
|
+
? this.getUTCFullYear() + '-' +
|
181
|
+
f(this.getUTCMonth() + 1) + '-' +
|
182
|
+
f(this.getUTCDate()) + 'T' +
|
183
|
+
f(this.getUTCHours()) + ':' +
|
184
|
+
f(this.getUTCMinutes()) + ':' +
|
185
|
+
f(this.getUTCSeconds()) + 'Z'
|
186
|
+
: null;
|
186
187
|
};
|
187
188
|
|
188
189
|
String.prototype.toJSON =
|
@@ -218,8 +219,9 @@ if (!JSON) {
|
|
218
219
|
escapable.lastIndex = 0;
|
219
220
|
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
|
220
221
|
var c = meta[a];
|
221
|
-
return typeof c === 'string'
|
222
|
-
|
222
|
+
return typeof c === 'string'
|
223
|
+
? c
|
224
|
+
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
223
225
|
}) + '"' : '"' + string + '"';
|
224
226
|
}
|
225
227
|
|
@@ -303,9 +305,11 @@ if (!JSON) {
|
|
303
305
|
// Join all of the elements together, separated with commas, and wrap them in
|
304
306
|
// brackets.
|
305
307
|
|
306
|
-
v = partial.length === 0
|
307
|
-
'[
|
308
|
-
|
308
|
+
v = partial.length === 0
|
309
|
+
? '[]'
|
310
|
+
: gap
|
311
|
+
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
|
312
|
+
: '[' + partial.join(',') + ']';
|
309
313
|
gap = mind;
|
310
314
|
return v;
|
311
315
|
}
|
@@ -340,9 +344,11 @@ if (!JSON) {
|
|
340
344
|
// Join all of the member texts together, separated with commas,
|
341
345
|
// and wrap them in braces.
|
342
346
|
|
343
|
-
v = partial.length === 0
|
344
|
-
'{
|
345
|
-
|
347
|
+
v = partial.length === 0
|
348
|
+
? '{}'
|
349
|
+
: gap
|
350
|
+
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
|
351
|
+
: '{' + partial.join(',') + '}';
|
346
352
|
gap = mind;
|
347
353
|
return v;
|
348
354
|
}
|
@@ -468,8 +474,9 @@ if (!JSON) {
|
|
468
474
|
// In the optional fourth stage, we recursively walk the new structure, passing
|
469
475
|
// each name/value pair to a reviver function for possible transformation.
|
470
476
|
|
471
|
-
return typeof reviver === 'function'
|
472
|
-
walk({'': j}, '')
|
477
|
+
return typeof reviver === 'function'
|
478
|
+
? walk({'': j}, '')
|
479
|
+
: j;
|
473
480
|
}
|
474
481
|
|
475
482
|
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
@@ -1,5 +1,5 @@
|
|
1
|
-
// Underscore.js 1.
|
2
|
-
// (c)
|
1
|
+
// Underscore.js 1.3.1
|
2
|
+
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
3
3
|
// Underscore is freely distributable under the MIT license.
|
4
4
|
// Portions of Underscore are inspired or borrowed from Prototype,
|
5
5
|
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
@@ -48,26 +48,21 @@
|
|
48
48
|
// Create a safe reference to the Underscore object for use below.
|
49
49
|
var _ = function(obj) { return new wrapper(obj); };
|
50
50
|
|
51
|
-
// Export the Underscore object for **Node.js
|
52
|
-
// backwards-compatibility for the old `require()` API. If we're
|
53
|
-
//
|
51
|
+
// Export the Underscore object for **Node.js**, with
|
52
|
+
// backwards-compatibility for the old `require()` API. If we're in
|
53
|
+
// the browser, add `_` as a global object via a string identifier,
|
54
|
+
// for Closure Compiler "advanced" mode.
|
54
55
|
if (typeof exports !== 'undefined') {
|
55
56
|
if (typeof module !== 'undefined' && module.exports) {
|
56
57
|
exports = module.exports = _;
|
57
58
|
}
|
58
59
|
exports._ = _;
|
59
|
-
} else if (typeof define === 'function' && define.amd) {
|
60
|
-
// Register as a named module with AMD.
|
61
|
-
define('underscore', function() {
|
62
|
-
return _;
|
63
|
-
});
|
64
60
|
} else {
|
65
|
-
// Exported as a string, for Closure Compiler "advanced" mode.
|
66
61
|
root['_'] = _;
|
67
62
|
}
|
68
63
|
|
69
64
|
// Current version.
|
70
|
-
_.VERSION = '1.
|
65
|
+
_.VERSION = '1.3.1';
|
71
66
|
|
72
67
|
// Collection Functions
|
73
68
|
// --------------------
|
@@ -85,7 +80,7 @@
|
|
85
80
|
}
|
86
81
|
} else {
|
87
82
|
for (var key in obj) {
|
88
|
-
if (
|
83
|
+
if (_.has(obj, key)) {
|
89
84
|
if (iterator.call(context, obj[key], key, obj) === breaker) return;
|
90
85
|
}
|
91
86
|
}
|
@@ -94,20 +89,21 @@
|
|
94
89
|
|
95
90
|
// Return the results of applying the iterator to each element.
|
96
91
|
// Delegates to **ECMAScript 5**'s native `map` if available.
|
97
|
-
_.map = function(obj, iterator, context) {
|
92
|
+
_.map = _.collect = function(obj, iterator, context) {
|
98
93
|
var results = [];
|
99
94
|
if (obj == null) return results;
|
100
95
|
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
101
96
|
each(obj, function(value, index, list) {
|
102
97
|
results[results.length] = iterator.call(context, value, index, list);
|
103
98
|
});
|
99
|
+
if (obj.length === +obj.length) results.length = obj.length;
|
104
100
|
return results;
|
105
101
|
};
|
106
102
|
|
107
103
|
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
108
104
|
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
109
105
|
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
110
|
-
var initial =
|
106
|
+
var initial = arguments.length > 2;
|
111
107
|
if (obj == null) obj = [];
|
112
108
|
if (nativeReduce && obj.reduce === nativeReduce) {
|
113
109
|
if (context) iterator = _.bind(iterator, context);
|
@@ -121,20 +117,22 @@
|
|
121
117
|
memo = iterator.call(context, memo, value, index, list);
|
122
118
|
}
|
123
119
|
});
|
124
|
-
if (!initial) throw new TypeError(
|
120
|
+
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
125
121
|
return memo;
|
126
122
|
};
|
127
123
|
|
128
124
|
// The right-associative version of reduce, also known as `foldr`.
|
129
125
|
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
130
126
|
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
127
|
+
var initial = arguments.length > 2;
|
131
128
|
if (obj == null) obj = [];
|
132
129
|
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
133
130
|
if (context) iterator = _.bind(iterator, context);
|
134
|
-
return
|
131
|
+
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
135
132
|
}
|
136
|
-
var reversed =
|
137
|
-
|
133
|
+
var reversed = _.toArray(obj).reverse();
|
134
|
+
if (context && !initial) iterator = _.bind(iterator, context);
|
135
|
+
return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
|
138
136
|
};
|
139
137
|
|
140
138
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
@@ -189,7 +187,7 @@
|
|
189
187
|
// Delegates to **ECMAScript 5**'s native `some` if available.
|
190
188
|
// Aliased as `any`.
|
191
189
|
var any = _.some = _.any = function(obj, iterator, context) {
|
192
|
-
iterator
|
190
|
+
iterator || (iterator = _.identity);
|
193
191
|
var result = false;
|
194
192
|
if (obj == null) return result;
|
195
193
|
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
@@ -215,7 +213,7 @@
|
|
215
213
|
_.invoke = function(obj, method) {
|
216
214
|
var args = slice.call(arguments, 2);
|
217
215
|
return _.map(obj, function(value) {
|
218
|
-
return (method
|
216
|
+
return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
|
219
217
|
});
|
220
218
|
};
|
221
219
|
|
@@ -402,10 +400,11 @@
|
|
402
400
|
});
|
403
401
|
};
|
404
402
|
|
405
|
-
// Take the difference between one array and
|
403
|
+
// Take the difference between one array and a number of other arrays.
|
406
404
|
// Only the elements present in just the first array will remain.
|
407
|
-
_.difference = function(array
|
408
|
-
|
405
|
+
_.difference = function(array) {
|
406
|
+
var rest = _.flatten(slice.call(arguments, 1));
|
407
|
+
return _.filter(array, function(value){ return !_.include(rest, value); });
|
409
408
|
};
|
410
409
|
|
411
410
|
// Zip together multiple lists into a single array -- elements that share
|
@@ -432,7 +431,7 @@
|
|
432
431
|
return array[i] === item ? i : -1;
|
433
432
|
}
|
434
433
|
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
435
|
-
for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
|
434
|
+
for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
|
436
435
|
return -1;
|
437
436
|
};
|
438
437
|
|
@@ -441,7 +440,7 @@
|
|
441
440
|
if (array == null) return -1;
|
442
441
|
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
443
442
|
var i = array.length;
|
444
|
-
while (i--) if (array[i] === item) return i;
|
443
|
+
while (i--) if (i in array && array[i] === item) return i;
|
445
444
|
return -1;
|
446
445
|
};
|
447
446
|
|
@@ -507,7 +506,7 @@
|
|
507
506
|
hasher || (hasher = _.identity);
|
508
507
|
return function() {
|
509
508
|
var key = hasher.apply(this, arguments);
|
510
|
-
return
|
509
|
+
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
|
511
510
|
};
|
512
511
|
};
|
513
512
|
|
@@ -579,7 +578,7 @@
|
|
579
578
|
// conditionally execute the original function.
|
580
579
|
_.wrap = function(func, wrapper) {
|
581
580
|
return function() {
|
582
|
-
var args = [func].concat(slice.call(arguments));
|
581
|
+
var args = [func].concat(slice.call(arguments, 0));
|
583
582
|
return wrapper.apply(this, args);
|
584
583
|
};
|
585
584
|
};
|
@@ -587,9 +586,9 @@
|
|
587
586
|
// Returns a function that is the composition of a list of functions, each
|
588
587
|
// consuming the return value of the function that follows.
|
589
588
|
_.compose = function() {
|
590
|
-
var funcs =
|
589
|
+
var funcs = arguments;
|
591
590
|
return function() {
|
592
|
-
var args =
|
591
|
+
var args = arguments;
|
593
592
|
for (var i = funcs.length - 1; i >= 0; i--) {
|
594
593
|
args = [funcs[i].apply(this, args)];
|
595
594
|
}
|
@@ -613,7 +612,7 @@
|
|
613
612
|
_.keys = nativeKeys || function(obj) {
|
614
613
|
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
615
614
|
var keys = [];
|
616
|
-
for (var key in obj) if (
|
615
|
+
for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
|
617
616
|
return keys;
|
618
617
|
};
|
619
618
|
|
@@ -636,7 +635,7 @@
|
|
636
635
|
_.extend = function(obj) {
|
637
636
|
each(slice.call(arguments, 1), function(source) {
|
638
637
|
for (var prop in source) {
|
639
|
-
|
638
|
+
obj[prop] = source[prop];
|
640
639
|
}
|
641
640
|
});
|
642
641
|
return obj;
|
@@ -677,8 +676,8 @@
|
|
677
676
|
if (a._chain) a = a._wrapped;
|
678
677
|
if (b._chain) b = b._wrapped;
|
679
678
|
// Invoke a custom `isEqual` method if one is provided.
|
680
|
-
if (_.isFunction(a.isEqual)) return a.isEqual(b);
|
681
|
-
if (_.isFunction(b.isEqual)) return b.isEqual(a);
|
679
|
+
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
|
680
|
+
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
|
682
681
|
// Compare `[[Class]]` names.
|
683
682
|
var className = toString.call(a);
|
684
683
|
if (className != toString.call(b)) return false;
|
@@ -687,13 +686,11 @@
|
|
687
686
|
case '[object String]':
|
688
687
|
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
689
688
|
// equivalent to `new String("5")`.
|
690
|
-
return
|
689
|
+
return a == String(b);
|
691
690
|
case '[object Number]':
|
692
|
-
a = +a;
|
693
|
-
b = +b;
|
694
691
|
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
|
695
692
|
// other numeric values.
|
696
|
-
return a != a ? b != b : (a == 0 ? 1 / a == 1 / b : a == b);
|
693
|
+
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
|
697
694
|
case '[object Date]':
|
698
695
|
case '[object Boolean]':
|
699
696
|
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
@@ -733,20 +730,20 @@
|
|
733
730
|
}
|
734
731
|
} else {
|
735
732
|
// Objects with different constructors are not equivalent.
|
736
|
-
if (
|
733
|
+
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
|
737
734
|
// Deep compare objects.
|
738
735
|
for (var key in a) {
|
739
|
-
if (
|
736
|
+
if (_.has(a, key)) {
|
740
737
|
// Count the expected number of properties.
|
741
738
|
size++;
|
742
739
|
// Deep compare each member.
|
743
|
-
if (!(result =
|
740
|
+
if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
|
744
741
|
}
|
745
742
|
}
|
746
743
|
// Ensure that both objects contain the same number of properties.
|
747
744
|
if (result) {
|
748
745
|
for (key in b) {
|
749
|
-
if (
|
746
|
+
if (_.has(b, key) && !(size--)) break;
|
750
747
|
}
|
751
748
|
result = !size;
|
752
749
|
}
|
@@ -765,7 +762,7 @@
|
|
765
762
|
// An "empty" object has no enumerable own-properties.
|
766
763
|
_.isEmpty = function(obj) {
|
767
764
|
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
768
|
-
for (var key in obj) if (
|
765
|
+
for (var key in obj) if (_.has(obj, key)) return false;
|
769
766
|
return true;
|
770
767
|
};
|
771
768
|
|
@@ -786,13 +783,12 @@
|
|
786
783
|
};
|
787
784
|
|
788
785
|
// Is a given variable an arguments object?
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
} else {
|
786
|
+
_.isArguments = function(obj) {
|
787
|
+
return toString.call(obj) == '[object Arguments]';
|
788
|
+
};
|
789
|
+
if (!_.isArguments(arguments)) {
|
794
790
|
_.isArguments = function(obj) {
|
795
|
-
return !!(obj &&
|
791
|
+
return !!(obj && _.has(obj, 'callee'));
|
796
792
|
};
|
797
793
|
}
|
798
794
|
|
@@ -842,6 +838,11 @@
|
|
842
838
|
return obj === void 0;
|
843
839
|
};
|
844
840
|
|
841
|
+
// Has own property?
|
842
|
+
_.has = function(obj, key) {
|
843
|
+
return hasOwnProperty.call(obj, key);
|
844
|
+
};
|
845
|
+
|
845
846
|
// Utility Functions
|
846
847
|
// -----------------
|
847
848
|
|
@@ -891,6 +892,17 @@
|
|
891
892
|
escape : /<%-([\s\S]+?)%>/g
|
892
893
|
};
|
893
894
|
|
895
|
+
// When customizing `templateSettings`, if you don't want to define an
|
896
|
+
// interpolation, evaluation or escaping regex, we need one that is
|
897
|
+
// guaranteed not to match.
|
898
|
+
var noMatch = /.^/;
|
899
|
+
|
900
|
+
// Within an interpolation, evaluation, or escaping, remove HTML escaping
|
901
|
+
// that had been previously added.
|
902
|
+
var unescape = function(code) {
|
903
|
+
return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
|
904
|
+
};
|
905
|
+
|
894
906
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
895
907
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
896
908
|
// and correctly escapes quotes within interpolated code.
|
@@ -900,22 +912,29 @@
|
|
900
912
|
'with(obj||{}){__p.push(\'' +
|
901
913
|
str.replace(/\\/g, '\\\\')
|
902
914
|
.replace(/'/g, "\\'")
|
903
|
-
.replace(c.escape, function(match, code) {
|
904
|
-
return "',_.escape(" + code
|
915
|
+
.replace(c.escape || noMatch, function(match, code) {
|
916
|
+
return "',_.escape(" + unescape(code) + "),'";
|
905
917
|
})
|
906
|
-
.replace(c.interpolate, function(match, code) {
|
907
|
-
return "'," + code
|
918
|
+
.replace(c.interpolate || noMatch, function(match, code) {
|
919
|
+
return "'," + unescape(code) + ",'";
|
908
920
|
})
|
909
|
-
.replace(c.evaluate ||
|
910
|
-
return "');" + code.replace(
|
911
|
-
.replace(/[\r\n\t]/g, ' ') + ";__p.push('";
|
921
|
+
.replace(c.evaluate || noMatch, function(match, code) {
|
922
|
+
return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
|
912
923
|
})
|
913
924
|
.replace(/\r/g, '\\r')
|
914
925
|
.replace(/\n/g, '\\n')
|
915
926
|
.replace(/\t/g, '\\t')
|
916
927
|
+ "');}return __p.join('');";
|
917
928
|
var func = new Function('obj', '_', tmpl);
|
918
|
-
|
929
|
+
if (data) return func(data, _);
|
930
|
+
return function(data) {
|
931
|
+
return func.call(this, data, _);
|
932
|
+
};
|
933
|
+
};
|
934
|
+
|
935
|
+
// Add a "chain" function, which will delegate to the wrapper.
|
936
|
+
_.chain = function(obj) {
|
937
|
+
return _(obj).chain();
|
919
938
|
};
|
920
939
|
|
921
940
|
// The OOP Wrapper
|
@@ -950,8 +969,11 @@
|
|
950
969
|
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
951
970
|
var method = ArrayProto[name];
|
952
971
|
wrapper.prototype[name] = function() {
|
953
|
-
|
954
|
-
|
972
|
+
var wrapped = this._wrapped;
|
973
|
+
method.apply(wrapped, arguments);
|
974
|
+
var length = wrapped.length;
|
975
|
+
if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
|
976
|
+
return result(wrapped, this._chain);
|
955
977
|
};
|
956
978
|
});
|
957
979
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backbone-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-02-06 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &2157255900 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: 3.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2157255900
|
25
25
|
description: Ships backbone and underscore to your Rails 3.1 application through the
|
26
26
|
new asset pipeline. Rails 3.0 is supported via generators.
|
27
27
|
email:
|
@@ -60,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
60
|
version: 1.3.6
|
61
61
|
requirements: []
|
62
62
|
rubyforge_project:
|
63
|
-
rubygems_version: 1.8.
|
63
|
+
rubygems_version: 1.8.11
|
64
64
|
signing_key:
|
65
65
|
specification_version: 3
|
66
66
|
summary: backbone and underscore for Rails
|