<commit_before>	// This is the base Model class in KnockoutApp
	var Model = KnockoutApp.Model = function(attributes, collection){

		// 'id' is an observable property, initially set to 'false'
		this.id = ko.observable(false);

		// The model stores its data inside this object
		this.attributes = {};

		// If an 'attributes' object is passed as a parameter:
		if(attributes){

			// In case it contains an 'id' property set **this.id()** value to it and delete it from the attributes object 
			if(attributes.id){
				this.id(attributes.id);
				delete attributes.id;
			}

			// Merge the attributes passed as parameters with the default attributes stored inside **this.defaultAttributes()**
			//
			// Using **Utils.extendObjKnockout** ensured that observable properties inside *this.defaultAttributes()*
			// are correctly set into *this.attributes*
			this.attributes = Utils.extendObjKnockout(this.defaultAttributes(), attributes);
		}

		// This function allows to be passed, as the second parameter, a reference to a **Collection**.
		// In that case a reference to the collection is set as *this.collection*
		if(collection) this.collection = collection;

		// Detect if the model has been created on the server by checking if the 'id' property is defined
		this.isNew = ko.computed(function(){
			return (this.id() === false) ? true : false;
		}, this);

		// Instead of overriding the function constructor use the initialize function to execute custom code on model creation
		// Knockout's observable properties can't be defined in the class prototype 
		// so this is the perfect place to use them.
		if(this.initialize) this.initialize.apply(this, arguments);

	};

	// Extend Model's prototype
	ko.utils.extend(Model.prototype, {

		// An object with the default attributes for the model 
		// It must be a function because no 'clone' method has been implemented so far, will be fixed in future versions
		// Here you can also use observable properties.
		defaultAttributes: function(){
			return {};
		},

		// Returns the model url on the server using the model's baseUrl or collection's url properties
		url: function(){
			var base = this.baseUrl || this.collection.url;
			if(this.isNew()) return base;
			return base + (base[base.length-1] === '/' ? '' : '/') + this.id();
		},

    // Validation method, should return TRUE if the model is valid
		validate: function(){
			return true;
		},

		// Fetch the model on the server and replace its attributes with the one fetched
		// Options for the Ajax call can be passed as a parameter
		fetch: function(_options){
			var self = this,
					options = {};

			options.succes = function(data){
				delete data.id;
				self.attributes = Utils.extendObjKnockout(self.defaultAttributes(), data);
			};
			
			options.error = function(){
				Utils.wrapError(arguments);
			};

			if(_options) ko.utils.extend(options, _options);

			return (this.sync || (this.collection && this.collection.sync) || KnockoutApp.Sync).call(this, 'fetch', this, options);
		},

		// Save the model on the server.
		// If this.isNew() returns true it will be created, otherwise it will be updated
		// Options for the Ajax call can be passed as a parameter
		save: function(_options){
			if(this.validate() !== true) return false;

			var self = this,
					options = {},
					method = this.isNew() ? 'create' : 'update';

			options.success = function(data){
				if(method === 'create') self.id(data.id);
			};

			options.error = function(){
				Utils.wrapError(arguments);
			};

			if(_options) ko.utils.extend(options, _options);

			return (this.sync || (this.collection && this.collection.sync) || KnockoutApp.Sync).call(this, method, this, options);
		},

		// Destroy the model on the server and remove it from its collection (if exists)
		// Options for the Ajax call can be passed as a parameter
		destroy: function(_options){
			if(this.isNew() && this.collection){
				this.collection.models.remove(this);
			}else if(!this.isNew()){
				var options = {},
						self = this;

				options.success = function(data){
					if(self.collection) self.collection.models.remove(self);
				};

				options.error = function(){
					Utils.wrapError(arguments);
				};

				if(_options) ko.utils.extend(options, _options);
				
				return (this.sync || (this.collection && this.collection.sync) || KnockoutApp.Sync).call(this, 'destroy', this, options);
			}
		},

		// Used for serialization, returns an object that contains model's attributes and its id
		toJSON: function(){
			var obj = ko.toJS(this.attributes);
			obj.id = this.id();
			return obj;
		}
	});<commit_msg>model.toJSON() now includes id only if it is set<commit_after>	// This is the base Model class in KnockoutApp
	var Model = KnockoutApp.Model = function(attributes, collection){

		// 'id' is an observable property, initially set to 'false'
		this.id = ko.observable(false);

		// The model stores its data inside this object
		this.attributes = {};

		// If an 'attributes' object is passed as a parameter:
		if(attributes){

			// In case it contains an 'id' property set **this.id()** value to it and delete it from the attributes object 
			if(attributes.id){
				this.id(attributes.id);
				delete attributes.id;
			}

			// Merge the attributes passed as parameters with the default attributes stored inside **this.defaultAttributes()**
			//
			// Using **Utils.extendObjKnockout** ensured that observable properties inside *this.defaultAttributes()*
			// are correctly set into *this.attributes*
			this.attributes = Utils.extendObjKnockout(this.defaultAttributes(), attributes);
		}

		// This function allows to be passed, as the second parameter, a reference to a **Collection**.
		// In that case a reference to the collection is set as *this.collection*
		if(collection) this.collection = collection;

		// Detect if the model has been created on the server by checking if the 'id' property is defined
		this.isNew = ko.computed(function(){
			return (this.id() === false) ? true : false;
		}, this);

		// Instead of overriding the function constructor use the initialize function to execute custom code on model creation
		// Knockout's observable properties can't be defined in the class prototype 
		// so this is the perfect place to use them.
		if(this.initialize) this.initialize.apply(this, arguments);

	};

	// Extend Model's prototype
	ko.utils.extend(Model.prototype, {

		// An object with the default attributes for the model 
		// It must be a function because no 'clone' method has been implemented so far, will be fixed in future versions
		// Here you can also use observable properties.
		defaultAttributes: function(){
			return {};
		},

		// Returns the model url on the server using the model's baseUrl or collection's url properties
		url: function(){
			var base = this.baseUrl || this.collection.url;
			if(this.isNew()) return base;
			return base + (base[base.length-1] === '/' ? '' : '/') + this.id();
		},

    // Validation method, should return TRUE if the model is valid
		validate: function(){
			return true;
		},

		// Fetch the model on the server and replace its attributes with the one fetched
		// Options for the Ajax call can be passed as a parameter
		fetch: function(_options){
			var self = this,
					options = {};

			options.succes = function(data){
				delete data.id;
				self.attributes = Utils.extendObjKnockout(self.defaultAttributes(), data);
			};
			
			options.error = function(){
				Utils.wrapError(arguments);
			};

			if(_options) ko.utils.extend(options, _options);

			return (this.sync || (this.collection && this.collection.sync) || KnockoutApp.Sync).call(this, 'fetch', this, options);
		},

		// Save the model on the server.
		// If this.isNew() returns true it will be created, otherwise it will be updated
		// Options for the Ajax call can be passed as a parameter
		save: function(_options){
			if(this.validate() !== true) return false;

			var self = this,
					options = {},
					method = this.isNew() ? 'create' : 'update';

			options.success = function(data){
				if(method === 'create') self.id(data.id);
			};

			options.error = function(){
				Utils.wrapError(arguments);
			};

			if(_options) ko.utils.extend(options, _options);

			return (this.sync || (this.collection && this.collection.sync) || KnockoutApp.Sync).call(this, method, this, options);
		},

		// Destroy the model on the server and remove it from its collection (if exists)
		// Options for the Ajax call can be passed as a parameter
		destroy: function(_options){
			if(this.isNew() && this.collection){
				this.collection.models.remove(this);
			}else if(!this.isNew()){
				var options = {},
						self = this;

				options.success = function(data){
					if(self.collection) self.collection.models.remove(self);
				};

				options.error = function(){
					Utils.wrapError(arguments);
				};

				if(_options) ko.utils.extend(options, _options);
				
				return (this.sync || (this.collection && this.collection.sync) || KnockoutApp.Sync).call(this, 'destroy', this, options);
			}
		},

		// Used for serialization, returns an object that contains model's attributes and its id
		toJSON: function(){
			var obj = ko.toJS(this.attributes);
			if(this.id()) obj.id = this.id();
			return obj;
		}
	});
{'fraction_non_alphanumeric': 0.12143395413930455, 'fraction_numerical': 0.00021530842932500807, 'mean_word_length': 3.3779453345900095, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6665334', 'n_tokens_mistral': 3055, 'n_tokens_neox': 2560, 'n_words': 943}