// Cons: make code too redundant
var MyModel = Backbone.Model.extend({
initialize: function() {
this.updateDerivedAttributes();
this.on('change:start_at', this.updateDerivedAttributes, this);
},
updateDerivedAttributes: function() {
this.set({
start_date: Utils.dateFromDate( this.get( "start_at" ) ),
start_time: Utils.timeFromDate( this.get( "start_at" ) ),
duration: Utils.youGetTheIdea()
}, {silent:true});
}
// override `toJSON` method
// set viewOnlyAttrs for attributes no need to save
viewOnlyAttrs: ['start_date', 'start_time', 'duration'],
toJSON: function(options) {
var obj = this;
// if is calling from model's save method
if(_.has(options || {}, 'emulateHTTP') && obj.viewOnlyAttrs)
return _.omit(obj.attributes, obj.viewOnlyAttrs);
return Backbone.Model.prototype.toJSON.call(this, options);
}
})
Cons: cannot get derived attribute by model's get
method,
and is not work well with collection as collection call model's toJSON
not toJSONDecorated
toJSONDecorated: function() {
return
_.extend(
this.toJSON(),
{
start_date : Utils.dateFromDate( this.get( "start_at" ) ),
start_time : Utils.timeFromDate( this.get( "start_at" ) ),
duration : Utils.youGetTheIdea( :) )
}
);
}
In fact, these are not derived attributes
Cons: if want to get these attributes in view template, you cannot use model's toJSON
method, instead, feed model instance in it
getUrl: function() {
return 'urlPrefix/' + this.get('id');
}
var MyModel = BaseModel.extend({
defaults: {
avg: function(){
return (this.get('min') + this.get('max')) / 2;
}
}
});
// need to override `get` and `toJSON` methods
Backbone.Model.extend({
get: function(attr) {
var value = Backbone.Model.prototype.get.call(this, attr);
return _.isFunction(value) ? value.call(this) : value;
},
toJSON: function(options) {
var data = {};
var json = Backbone.Model.prototype.toJSON.call(this);
_.each(json, function(value, key) {
// filter isFunction value if is calling from model's save method
if(!_.has(options || {}, 'emulateHTTP') || !_.isFunction(value))
data[key] = this.get(key);
}, this);
return data;
}
});
See detail at Backbone.Mutators plugin
var User = Backbone.Model.extend({
// Define mutator properties
mutators: {
fullname: function () {
return this.get('firstname') + ' ' + this.get('lastname');
}
},
defaults: {
firstname: 'Sugar',
lastname: 'Daddy'
}
});
var user = new User();
// use get to get the 'mutated' value
user.get('fullname') // 'Sugar Daddy'
// serialize the model and see the 'mutated' value in the resulting JSON
user.toJSON() // '{firstname: 'Sugar', lastname: 'Daddy', fullname: 'Sugar Daddy'}'