Closed
Description
I overrode the set
method of one of my models to coerce values to Dates, but found that validation was failing when I tried to fetch the corresponding collection. This is because Collection._prepareModel
validates the passed attributes rather than getting a fresh set from the model, but the Model
constructor passes a new object to set
if defaults
is set. As a result, the changes made in set
are not reflected in the original attrs
object which is validated.
Relevant lines:
Model
constructor (135-138)
if (defaults = this.defaults) {
if (_.isFunction(defaults)) defaults = defaults.call(this);
attributes = _.extend({}, defaults, attributes);
}
Collection._prepareModel
(570-571)
model = new this.model(attrs, {collection: this});
if (model.validate && !model._performValidation(attrs, options)) model = false;
I think doing attributes = _.extend(attributes, defaults, attributes);
would work, but there's likely a better solution.
Test case:
var MyModel = Backbone.Model.extend({
defaults: {
theDate: null
},
validate: function (attributes) {
if (!_.isDate(attributes.theDate)) {
return 'theDate must be a date';
}
},
set: function (attributes, options) {
if (_.isNumber(attributes.theDate)) {
attributes.theDate = new Date(attributes.theDate);
}
Backbone.Model.prototype.set.call(this, attributes, options);
}
});
var model = new MyModel({ theDate: (new Date(1, 1, 2011)).getTime() });
console.log(model.get('theDate')); // Date {Sat Aug 04 1906 00:00:00 GMT-0500 (CST)}
var MyModelList = Backbone.Collection.extend({
model: MyModel
});
var list = new MyModelList([{ theDate: (new Date(1, 1, 2011)).getTime() }]);
console.log(list.length); // 0!