Search code examples
ember.jsember-dataember-cli

Monkey patching Ember Data (when using ember-cli)


Could anyone explain to me how to do monkey patching when using Ember CLI? It's about the following method:

https://github.com/emberjs/data/blob/fba5e5f09824caab3dfaf0e746f760b3eeacd269/packages/ember-data/lib/system/relationships/relationship.js#L284

BelongsToRelationship.prototype.addRecord = function(newRecord) {
  if (this.members.has(newRecord)){ return;}
  var type = this.relationshipMeta.type;
  Ember.assert("You can only add a '" + type.typeKey + "' record to this relationship", newRecord instanceof type);

  if (this.inverseRecord) {
    this.removeRecord(this.inverseRecord);
  }

  this.inverseRecord = newRecord;
  this._super$addRecord(newRecord);
};

I wish to temporarily disable the assert statement but I don't see how to do this without forking the whole project. I would then also need to fork the ember-data bower package project then and create my own distribution.

-- Thomas


Solution

  • BelongsToRelationship is not defined in a way it can be accessed via the global scope. However you can retrieve it by instantiating a model with DS.belongsTo relation and digging inside of it.

    This initializer should do the trick:

    // app/initializers/monkey-patch.js
    
    import DS from 'ember-data';
    import Ember from 'ember';
    
    //Hacky way to get BelongsToRelationship constructor
    var getBelongsToConstructor = function(store) {
      var dummyRecord = store.createRecord(DS.Model.extend({
        dummy: DS.belongsTo(DS.Model.extend())
      }));
      return dummyRecord._relationships.dummy.constructor;
    };
    
    export default {
      name: 'monkey-patch',
      after: 'store',
      initialize: function(container, application) {
        var store = container.lookup('store:main'),
          BelongsToRelationship = getBelongsToConstructor(store),
          originalAssert = Ember.assert,
          originalAddRecord = BelongsToRelationship.prototype.addRecord;
    
        //Overriding assert in order to check Ember.disableAssert flag
        Ember.assert = function() {
          var args = Array.prototype.slice.call(arguments, 0),
            retVal;
          if (!Ember.disableAssert) {
            retVal = originalAssert.apply(this, args);
          }
          return retVal;
        };
    
        //Overriding BelongsToRelationship - calling super while asserion is disabled
        BelongsToRelationship.prototype.addRecord = function() {
          var args = Array.prototype.slice.call(arguments, 0),
            retVal;
          Ember.disableAssert = true;
          retVal = originalAddRecord.apply(this, args);
          Ember.disableAssert = false;
          return retVal;
        };
      }
    };