[Pkg-javascript-commits] [backbone] 247/281: Overhauling 'validate' -- Receives the computed new state of the attrs, not just the delta. Now runs on model create, raising an exception if you try to 'new' and invalid model ... also runs even if changed silently.

Jonas Smedegaard js at moszumanska.debian.org
Sat May 3 17:02:18 UTC 2014


This is an automated email from the git hooks/post-receive script.

js pushed a commit to tag 0.9.0
in repository backbone.

commit ab164c450da4d5c883d5b2b2817fa6a416a4b55a
Author: Jeremy Ashkenas <jashkenas at gmail.com>
Date:   Mon Jan 23 18:16:20 2012 -0500

    Overhauling 'validate' -- Receives the computed new state of the attrs, not just the delta. Now runs on model create, raising an exception if you try to 'new' and invalid model ... also runs even if changed silently.
---
 backbone.js                                        |  9 ++--
 examples/todos/index.html                          |  2 +-
 index.html                                         |  2 +-
 test/collection.js                                 | 15 ++++--
 test/model.js                                      | 19 ++++----
 test/test-ender.html                               |  2 +-
 test/test-zepto.html                               |  2 +-
 test/test.html                                     |  2 +-
 .../{underscore-1.2.4.js => underscore-1.3.1.js}   | 56 ++++++++++++----------
 9 files changed, 59 insertions(+), 50 deletions(-)

diff --git a/backbone.js b/backbone.js
index 64ad380..f37cc79 100644
--- a/backbone.js
+++ b/backbone.js
@@ -161,7 +161,9 @@
     this.attributes = {};
     this._escapedAttributes = {};
     this.cid = _.uniqueId('c');
-    this.set(attributes, {silent: true});
+    if (!this.set(attributes, {silent: true})) {
+      throw new Error("Can't create an invalid model");
+    }
     this._changed = false;
     this._previousAttributes = _.clone(this.attributes);
     this.initialize.apply(this, arguments);
@@ -225,7 +227,7 @@
       var now = this.attributes, escaped = this._escapedAttributes;
 
       // Run validation.
-      if (!options.silent && this.validate && !this._performValidation(attrs, options)) return false;
+      if (this.validate && !this._performValidation(attrs, options)) return false;
 
       // Check for changes of `id`.
       if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
@@ -422,7 +424,8 @@
     // if all is well. If a specific `error` callback has been passed,
     // call that instead of firing the general `"error"` event.
     _performValidation: function(attrs, options) {
-      var error = this.validate(attrs, options);
+      var newAttrs = _.extend({}, this.attributes, attrs);
+      var error = this.validate(newAttrs, options);
       if (error) {
         if (options.error) {
           options.error(this, error, options);
diff --git a/examples/todos/index.html b/examples/todos/index.html
index f437827..ec93e68 100644
--- a/examples/todos/index.html
+++ b/examples/todos/index.html
@@ -6,7 +6,7 @@
     <link href="todos.css" media="all" rel="stylesheet" type="text/css"/>
     <script src="../../test/vendor/json2.js"></script>
     <script src="../../test/vendor/jquery-1.7.1.js"></script>
-    <script src="../../test/vendor/underscore-1.2.4.js"></script>
+    <script src="../../test/vendor/underscore-1.3.1.js"></script>
     <script src="../../backbone.js"></script>
     <script src="../backbone-localstorage.js"></script>
     <script src="todos.js"></script>
diff --git a/index.html b/index.html
index f7cbf2e..d86fb42 100644
--- a/index.html
+++ b/index.html
@@ -3061,7 +3061,7 @@ Inbox.messages.add(newMessage);
 
   </div>
 
-  <script src="test/vendor/underscore-1.2.4.js"></script>
+  <script src="test/vendor/underscore-1.3.1.js"></script>
   <script src="test/vendor/jquery-1.7.1.js"></script>
   <script src="test/vendor/json2.js"></script>
   <script src="backbone.js"></script>
diff --git a/test/collection.js b/test/collection.js
index 2626003..6aa7bb9 100644
--- a/test/collection.js
+++ b/test/collection.js
@@ -73,8 +73,9 @@ $(document).ready(function() {
     var CustomSetCollection = Backbone.Collection.extend({
       model: CustomSetModel
     });
-    var col = new CustomSetCollection([{ num_as_string: 2 }]);
-    equal(col.length, 1);
+    raises(function(){
+      new CustomSetCollection([{ num_as_string: 2 }]);
+    });
   });
 
   test("Collection: update index when id changes", function() {
@@ -363,7 +364,9 @@ $(document).ready(function() {
       model: ValidatingModel
     });
     var col = new ValidatingCollection();
-    equal(col.create({"foo":"bar"}),false);
+    raises(function(){
+      equal(col.create({"foo":"bar"}),false);
+    });
   });
 
   test("Collection: a failing create runs the error callback", function() {
@@ -378,8 +381,9 @@ $(document).ready(function() {
     var flag = false;
     var callback = function(model, error) { flag = true; };
     var col = new ValidatingCollection();
-    col.create({"foo":"bar"}, { error: callback });
-    equal(flag, true);
+    raises(function(){
+      col.create({"foo":"bar"}, { error: callback });
+    });
   });
 
   test("collection: initialize", function() {
@@ -456,6 +460,7 @@ $(document).ready(function() {
       set: function(attrs) {
         equal(attrs.prop, 'value');
         equal(this.collection, col);
+        return this;
       }
     });
     col.model = Model;
diff --git a/test/model.js b/test/model.js
index fecfd82..66cd729 100644
--- a/test/model.js
+++ b/test/model.js
@@ -177,10 +177,10 @@ $(document).ready(function() {
     ok(changeCount == 1, "Change count should NOT have incremented.");
 
     a.validate = function(attrs) {
-      equal(attrs.foo, void 0, 'ignore values when unsetting');
+      equal(attrs.foo, void 0, "don't ignore values when unsetting");
     };
     a.unset('foo');
-    ok(a.get('foo') == null, "Foo should have changed");
+    equal(a.get('foo'), void 0, "Foo should have changed");
     delete a.validate;
     ok(changeCount == 2, "Change count should have incremented for unset.");
 
@@ -364,7 +364,7 @@ $(document).ready(function() {
     var lastError;
     var model = new Backbone.Model();
     model.validate = function(attrs) {
-      if (attrs.admin) return "Can't change admin status.";
+      if (attrs.admin != this.get('admin')) return "Can't change admin status.";
     };
     model.on('error', function(model, error) {
       lastError = error;
@@ -374,23 +374,20 @@ $(document).ready(function() {
     equal(model.get('a'), 100);
     equal(lastError, undefined);
     result = model.set({admin: true}, {silent: true});
-    equal(lastError, undefined);
-    equal(model.get('admin'), true);
+    equal(lastError, "Can't change admin status.");
+    equal(model.get('admin'), void 0);
     result = model.set({a: 200, admin: true});
     equal(result, false);
     equal(model.get('a'), 100);
-    equal(lastError, "Can't change admin status.");
   });
 
   test("Model: validate on unset and clear", function() {
     var error;
     var model = new Backbone.Model({name: "One"});
     model.validate = function(attrs) {
-      if ("name" in attrs) {
-        if (!attrs.name) {
-          error = true;
-          return "No thanks.";
-        }
+      if (!attrs.name) {
+        error = true;
+        return "No thanks.";
       }
     };
     model.set({name: "Two"});
diff --git a/test/test-ender.html b/test/test-ender.html
index 11aed5b..10f179c 100644
--- a/test/test-ender.html
+++ b/test/test-ender.html
@@ -7,7 +7,7 @@
   <script type="text/javascript" src="vendor/ender-jeesh.js"></script>
   <script type="text/javascript" src="vendor/qunit.js"></script>
   <script type="text/javascript" src="vendor/jslitmus.js"></script>
-  <script type="text/javascript" src="vendor/underscore-1.2.4.js"></script>
+  <script type="text/javascript" src="vendor/underscore-1.3.1.js"></script>
   <script type="text/javascript" src="../backbone.js"></script>
 
   <script type="text/javascript" src="events.js"></script>
diff --git a/test/test-zepto.html b/test/test-zepto.html
index d47ce0f..8a86b04 100644
--- a/test/test-zepto.html
+++ b/test/test-zepto.html
@@ -7,7 +7,7 @@
   <script type="text/javascript" src="vendor/zepto-0.6.js"></script>
   <script type="text/javascript" src="vendor/qunit.js"></script>
   <script type="text/javascript" src="vendor/jslitmus.js"></script>
-  <script type="text/javascript" src="vendor/underscore-1.2.4.js"></script>
+  <script type="text/javascript" src="vendor/underscore-1.3.1.js"></script>
   <script type="text/javascript" src="../backbone.js"></script>
 
   <script type="text/javascript" src="events.js"></script>
diff --git a/test/test.html b/test/test.html
index 099d924..eb7fa27 100644
--- a/test/test.html
+++ b/test/test.html
@@ -10,7 +10,7 @@
     QUnit.config.reorder = false;
   </script>
   <script type="text/javascript" src="vendor/jslitmus.js"></script>
-  <script type="text/javascript" src="vendor/underscore-1.2.4.js"></script>
+  <script type="text/javascript" src="vendor/underscore-1.3.1.js"></script>
   <script type="text/javascript" src="../backbone.js"></script>
 
   <script type="text/javascript" src="noconflict.js"></script>
diff --git a/test/vendor/underscore-1.2.4.js b/test/vendor/underscore-1.3.1.js
similarity index 96%
rename from test/vendor/underscore-1.2.4.js
rename to test/vendor/underscore-1.3.1.js
index c8cd1fd..208d4cd 100644
--- a/test/vendor/underscore-1.2.4.js
+++ b/test/vendor/underscore-1.3.1.js
@@ -1,4 +1,4 @@
-//     Underscore.js 1.2.4
+//     Underscore.js 1.3.1
 //     (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
 //     Underscore is freely distributable under the MIT license.
 //     Portions of Underscore are inspired or borrowed from Prototype,
@@ -48,26 +48,21 @@
   // Create a safe reference to the Underscore object for use below.
   var _ = function(obj) { return new wrapper(obj); };
 
-  // Export the Underscore object for **Node.js** and **"CommonJS"**, with
-  // backwards-compatibility for the old `require()` API. If we're not in
-  // CommonJS, add `_` to the global object.
+  // Export the Underscore object for **Node.js**, with
+  // backwards-compatibility for the old `require()` API. If we're in
+  // the browser, add `_` as a global object via a string identifier,
+  // for Closure Compiler "advanced" mode.
   if (typeof exports !== 'undefined') {
     if (typeof module !== 'undefined' && module.exports) {
       exports = module.exports = _;
     }
     exports._ = _;
-  } else if (typeof define === 'function' && define.amd) {
-    // Register as a named module with AMD.
-    define('underscore', function() {
-      return _;
-    });
   } else {
-    // Exported as a string, for Closure Compiler "advanced" mode.
     root['_'] = _;
   }
 
   // Current version.
-  _.VERSION = '1.2.4';
+  _.VERSION = '1.3.1';
 
   // Collection Functions
   // --------------------
@@ -85,7 +80,7 @@
       }
     } else {
       for (var key in obj) {
-        if (hasOwnProperty.call(obj, key)) {
+        if (_.has(obj, key)) {
           if (iterator.call(context, obj[key], key, obj) === breaker) return;
         }
       }
@@ -94,7 +89,7 @@
 
   // Return the results of applying the iterator to each element.
   // Delegates to **ECMAScript 5**'s native `map` if available.
-  _.map = function(obj, iterator, context) {
+  _.map = _.collect = function(obj, iterator, context) {
     var results = [];
     if (obj == null) return results;
     if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
@@ -511,7 +506,7 @@
     hasher || (hasher = _.identity);
     return function() {
       var key = hasher.apply(this, arguments);
-      return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
     };
   };
 
@@ -617,7 +612,7 @@
   _.keys = nativeKeys || function(obj) {
     if (obj !== Object(obj)) throw new TypeError('Invalid object');
     var keys = [];
-    for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
+    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
     return keys;
   };
 
@@ -640,7 +635,7 @@
   _.extend = function(obj) {
     each(slice.call(arguments, 1), function(source) {
       for (var prop in source) {
-        if (source[prop] !== void 0) obj[prop] = source[prop];
+        obj[prop] = source[prop];
       }
     });
     return obj;
@@ -738,17 +733,17 @@
       if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
       // Deep compare objects.
       for (var key in a) {
-        if (hasOwnProperty.call(a, key)) {
+        if (_.has(a, key)) {
           // Count the expected number of properties.
           size++;
           // Deep compare each member.
-          if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
+          if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
         }
       }
       // Ensure that both objects contain the same number of properties.
       if (result) {
         for (key in b) {
-          if (hasOwnProperty.call(b, key) && !(size--)) break;
+          if (_.has(b, key) && !(size--)) break;
         }
         result = !size;
       }
@@ -767,7 +762,7 @@
   // An "empty" object has no enumerable own-properties.
   _.isEmpty = function(obj) {
     if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
-    for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
+    for (var key in obj) if (_.has(obj, key)) return false;
     return true;
   };
 
@@ -793,7 +788,7 @@
   };
   if (!_.isArguments(arguments)) {
     _.isArguments = function(obj) {
-      return !!(obj && hasOwnProperty.call(obj, 'callee'));
+      return !!(obj && _.has(obj, 'callee'));
     };
   }
 
@@ -843,6 +838,11 @@
     return obj === void 0;
   };
 
+  // Has own property?
+  _.has = function(obj, key) {
+    return hasOwnProperty.call(obj, key);
+  };
+
   // Utility Functions
   // -----------------
 
@@ -897,6 +897,12 @@
   // guaranteed not to match.
   var noMatch = /.^/;
 
+  // Within an interpolation, evaluation, or escaping, remove HTML escaping
+  // that had been previously added.
+  var unescape = function(code) {
+    return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
+  };
+
   // JavaScript micro-templating, similar to John Resig's implementation.
   // Underscore templating handles arbitrary delimiters, preserves whitespace,
   // and correctly escapes quotes within interpolated code.
@@ -907,15 +913,13 @@
       str.replace(/\\/g, '\\\\')
          .replace(/'/g, "\\'")
          .replace(c.escape || noMatch, function(match, code) {
-           return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
+           return "',_.escape(" + unescape(code) + "),'";
          })
          .replace(c.interpolate || noMatch, function(match, code) {
-           return "'," + code.replace(/\\'/g, "'") + ",'";
+           return "'," + unescape(code) + ",'";
          })
          .replace(c.evaluate || noMatch, function(match, code) {
-           return "');" + code.replace(/\\'/g, "'")
-                              .replace(/[\r\n\t]/g, ' ')
-                              .replace(/\\\\/g, '\\') + ";__p.push('";
+           return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
          })
          .replace(/\r/g, '\\r')
          .replace(/\n/g, '\\n')

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/backbone.git



More information about the Pkg-javascript-commits mailing list