<commit_before>import { transaction } from 'mobservable';
import { tableize, underscore } from 'inflection';
import findWhere from 'lodash/collection/findWhere';
import filter from 'lodash/collection/filter';

import initAttributes from './init_attributes';
import setAttributes from './set_attributes';
import initRelations from './init_relations';
import setRelations from './set_relations';


class BaseModel {

  static urlRoot = null;
  static jsonKey = null;
  static attributes = {}; 
  static relations = [];

  id = null;
  lastSetRequestId = null;

  static config = function(options = {}) {
    let { models } = options;
    this.models = models;
  };

  static get = function(id) {
    if (!this.collection) this.collection = [];
    return findWhere(this.collection, { id: parseInt(id) });
  };  

  static set = function(options = {}) {
    if (!this.collection) this.collection = [];

    // console.log('set static', this.name)

    let { modelJson, topLevelJson, requestId } = options;
    let model = this.get(modelJson.id);
    
    if (!model) {
      model = new this({
        modelJson,
        topLevelJson,
        requestId
      })

      this.collection.push(model);
    }
    
    model.set({ modelJson, topLevelJson, requestId });

    // console.log('set', model)

    return model;
  };

  static remove = function (model) {
    this.collection.splice(this.collection.indexOf(model), 1);
  };

  static all = function() {
    return this.collection.slice();
  };

  static addClassAction(actionName, method) {
    Object.defineProperty(this, actionName, {
      get: function() {
        return method.bind(this);
      }
    });
  }

  static addAction(actionName, method) {
    Object.defineProperty(this.prototype, actionName, {
      get: function() {
        return method.bind(this);
      }
    });
  }
  
  constructor(options = {}) {
    let { 
      modelJson,
      topLevelJson,
      requestId
    } = options;

    this.id = modelJson.id;    

    initAttributes({ model: this });
    initRelations({ model: this });
  }


  set(options = {}) {
    let { requestId, modelJson, topLevelJson } = options;
    let model = this;

    if (this.lastSetRequestId === requestId) {
      return;
    } else {
      this.lastSetRequestId = requestId;
    }

    transaction(() => {
      setAttributes({ model, modelJson });
      
      setRelations({
        model,
        requestId,
        modelJson,
        topLevelJson
      });
    });
  }


  get urlRoot() {
    return this.constructor.urlRoot;
  }

  get jsonKey() {
    return this.constructor.jsonKey;
  }

  onDestroy() {    
    transaction(() => {
      this.removeSelfFromCollection();        
      this.destroyDependentRelations();
      this.removeSelfFromRelations();
    });
  }

  removeSelfFromCollection() {
    this.constructor.remove(this);
  }

  destroyDependentRelations() {
    let relationsToDestroy = filter(this.constructor.relations, relation => {
      let reverseRelation = relation.reverseRelation;
      return reverseRelation && reverseRelation.onDestroy === 'destroyRelation';
    });

    relationsToDestroy.forEach(relation => {
      if (relation.isHasMany) {
        this[relation.propertyName].slice().forEach(relatedModel => {
          relatedModel.onDestroy();
        })
      } else if (relation.isHasOne) {
        this[relation.propertyName].onDestroy();
      }
    })
  }

  removeSelfFromRelations() {

    let relationsToRemoveFrom = filter(this.constructor.relations, relation => {
      let reverseRelation = relation.reverseRelation;
      return reverseRelation && reverseRelation.onDestroy === 'removeSelf';
    });

    relationsToRemoveFrom.forEach(relation => {

      let removeMethodName = relation.reverseRelation.removeMethodName;

      if (relation.isHasMany) {
        this[relation.propertyName].slice().forEach(relatedModel => {
          relatedModel[removeMethodName](this);
        })
      } else if (relation.isHasOne) {
        // console.log(relation.propertyName, removeMethodName, this[relation.propertyName])
        this[relation.propertyName][removeMethodName](this);
      }
    })
  }

}

Object.defineProperty(BaseModel, 'urlRoot', {
  get: function() {
    return '/'+tableize(this.name);
  }
});

Object.defineProperty(BaseModel, 'jsonKey', {
  get: function() {
    return underscore(this.name);
  }
});


export default BaseModel;<commit_msg>remove self only from relations that supports that<commit_after>import { transaction } from 'mobservable';
import { tableize, underscore } from 'inflection';
import findWhere from 'lodash/collection/findWhere';
import filter from 'lodash/collection/filter';

import initAttributes from './init_attributes';
import setAttributes from './set_attributes';
import initRelations from './init_relations';
import setRelations from './set_relations';


class BaseModel {

  static urlRoot = null;
  static jsonKey = null;
  static attributes = {}; 
  static relations = [];

  id = null;
  lastSetRequestId = null;

  static config = function(options = {}) {
    let { models } = options;
    this.models = models;
  };

  static get = function(id) {
    if (!this.collection) this.collection = [];
    return findWhere(this.collection, { id: parseInt(id) });
  };  

  static set = function(options = {}) {
    if (!this.collection) this.collection = [];

    // console.log('set static', this.name)

    let { modelJson, topLevelJson, requestId } = options;
    let model = this.get(modelJson.id);
    
    if (!model) {
      model = new this({
        modelJson,
        topLevelJson,
        requestId
      })

      this.collection.push(model);
    }
    
    model.set({ modelJson, topLevelJson, requestId });

    // console.log('set', model)

    return model;
  };

  static remove = function (model) {
    this.collection.splice(this.collection.indexOf(model), 1);
  };

  static all = function() {
    return this.collection.slice();
  };

  static addClassAction(actionName, method) {
    Object.defineProperty(this, actionName, {
      get: function() {
        return method.bind(this);
      }
    });
  }

  static addAction(actionName, method) {
    Object.defineProperty(this.prototype, actionName, {
      get: function() {
        return method.bind(this);
      }
    });
  }
  
  constructor(options = {}) {
    let { 
      modelJson,
      topLevelJson,
      requestId
    } = options;

    this.id = modelJson.id;    

    initAttributes({ model: this });
    initRelations({ model: this });
  }


  set(options = {}) {
    let { requestId, modelJson, topLevelJson } = options;
    let model = this;

    if (this.lastSetRequestId === requestId) {
      return;
    } else {
      this.lastSetRequestId = requestId;
    }

    transaction(() => {
      setAttributes({ model, modelJson });
      
      setRelations({
        model,
        requestId,
        modelJson,
        topLevelJson
      });
    });
  }


  get urlRoot() {
    return this.constructor.urlRoot;
  }

  get jsonKey() {
    return this.constructor.jsonKey;
  }

  onDestroy() {    
    transaction(() => {
      this.removeSelfFromCollection();        
      this.destroyDependentRelations();
      this.removeSelfFromRelations();
    });
  }

  removeSelfFromCollection() {
    this.constructor.remove(this);
  }

  destroyDependentRelations() {
    let relationsToDestroy = filter(this.constructor.relations, relation => {
      let reverseRelation = relation.reverseRelation;
      return reverseRelation && reverseRelation.onDestroy === 'destroyRelation';
    });

    relationsToDestroy.forEach(relation => {
      if (relation.isHasMany) {
        this[relation.propertyName].slice().forEach(relatedModel => {
          relatedModel.onDestroy();
        })
      } else if (relation.isHasOne) {
        this[relation.propertyName].onDestroy();
      }
    })
  }

  removeSelfFromRelations() {

    let relationsToRemoveFrom = filter(this.constructor.relations, relation => {
      let reverseRelation = relation.reverseRelation;
      return reverseRelation && reverseRelation.onDestroy === 'removeSelf';
    });

    relationsToRemoveFrom.forEach(relation => {

      let removeMethodName = relation.reverseRelation.removeMethodName;

      if (relation.isHasMany) {
        this[relation.propertyName].slice().forEach(relatedModel => {
          if (relatedModel[removeMethodName]) {
            relatedModel[removeMethodName](this);
          }
        })
      } else if (relation.isHasOne) {
        // console.log(relation.propertyName, removeMethodName, this[relation.propertyName])
        if (this[relation.propertyName][removeMethodName]) {
          this[relation.propertyName][removeMethodName](this);
        }
      }
    })
  }

}

Object.defineProperty(BaseModel, 'urlRoot', {
  get: function() {
    return '/'+tableize(this.name);
  }
});

Object.defineProperty(BaseModel, 'jsonKey', {
  get: function() {
    return underscore(this.name);
  }
});


export default BaseModel;
{'fraction_non_alphanumeric': 0.12877107364685003, 'fraction_numerical': 0.00022182786157941438, 'mean_word_length': 2.8062473617560153, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, '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': '6914147', 'n_tokens_mistral': 2650, 'n_tokens_neox': 2556, 'n_words': 504}