diff --git a/backbone.js b/backbone.js index b8a36a6b..cdafdb47 100644 --- a/backbone.js +++ b/backbone.js @@ -304,6 +304,9 @@ options || (options = {}); + // Run validation. + if (!this._validate(attrs, options)) return false; + // Extract attributes and options. unset = options.unset; silent = options.silent; @@ -317,9 +320,6 @@ } current = this.attributes, prev = this._previousAttributes; - // Run validation. - if (!this._validate(attrs, options)) return false; - // Check for changes of `id`. if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; diff --git a/test/model.js b/test/model.js index 9bbbe4c8..5f3651f6 100644 --- a/test/model.js +++ b/test/model.js @@ -213,6 +213,24 @@ $(document).ready(function() { equal(a.id, undefined, "Unsetting the id should remove the id property."); }); + test("#2030 - set with failed validate, followed by another set triggers change", function () { + var attr = 0, main = 0, error = 0; + var Model = Backbone.Model.extend({ + validate: function (attr) { + if (attr.x > 1) { + error++; + return "this is an error"; + } + } + }); + var model = new Model({x:0}); + model.on('change:x', function () { attr++; }); + model.on('change', function () { main++; }); + model.set({x:2}, {validate:true}); + model.set({x:1}, {validate:true}); + deepEqual([attr, main, error], [1, 1, 1]); + }); + test("set triggers changes in the correct order", function() { var value = null; var model = new Backbone.Model;