diff --git a/addon/-private/system/relationships/state/belongs-to.js b/addon/-private/system/relationships/state/belongs-to.js
index 802708cc5b0..2b6089d828a 100644
--- a/addon/-private/system/relationships/state/belongs-to.js
+++ b/addon/-private/system/relationships/state/belongs-to.js
@@ -5,163 +5,156 @@ import {
 } from "ember-data/-private/system/promise-proxies";
 
 import { assertPolymorphicType } from "ember-data/-private/debug";
-
 import Relationship from "ember-data/-private/system/relationships/state/relationship";
 
-export default function BelongsToRelationship(store, record, inverseKey, relationshipMeta) {
-  this._super$constructor(store, record, inverseKey, relationshipMeta);
-  this.record = record;
-  this.key = relationshipMeta.key;
-  this.inverseRecord = null;
-  this.canonicalState = null;
-}
+export default class BelongsToRelationship extends Relationship {
+  constructor(store, internalModel, inverseKey, relationshipMeta) {
+    super(store, internalModel, inverseKey, relationshipMeta);
+    this.internalModel = internalModel;
+    this.key = relationshipMeta.key;
+    this.inverseRecord = null;
+    this.canonicalState = null;
+  }
 
-BelongsToRelationship.prototype = Object.create(Relationship.prototype);
-BelongsToRelationship.prototype.constructor = BelongsToRelationship;
-BelongsToRelationship.prototype._super$constructor = Relationship;
+  setRecord(newRecord) {
+    if (newRecord) {
+      this.addRecord(newRecord);
+    } else if (this.inverseRecord) {
+      this.removeRecord(this.inverseRecord);
+    }
+    this.setHasData(true);
+    this.setHasLoaded(true);
+  }
 
-BelongsToRelationship.prototype.setRecord = function(newRecord) {
-  if (newRecord) {
-    this.addRecord(newRecord);
-  } else if (this.inverseRecord) {
-    this.removeRecord(this.inverseRecord);
+  setCanonicalRecord(newRecord) {
+    if (newRecord) {
+      this.addCanonicalRecord(newRecord);
+    } else if (this.canonicalState) {
+      this.removeCanonicalRecord(this.canonicalState);
+    }
+    this.flushCanonicalLater();
   }
-  this.setHasData(true);
-  this.setHasLoaded(true);
-};
-
-BelongsToRelationship.prototype.setCanonicalRecord = function(newRecord) {
-  if (newRecord) {
-    this.addCanonicalRecord(newRecord);
-  } else if (this.canonicalState) {
-    this.removeCanonicalRecord(this.canonicalState);
+
+  addCanonicalRecord(newRecord) {
+    if (this.canonicalMembers.has(newRecord)) { return;}
+
+    if (this.canonicalState) {
+      this.removeCanonicalRecord(this.canonicalState);
+    }
+
+    this.canonicalState = newRecord;
+    super.addCanonicalRecord(newRecord);
   }
-  this.flushCanonicalLater();
-};
 
-BelongsToRelationship.prototype._super$addCanonicalRecord = Relationship.prototype.addCanonicalRecord;
-BelongsToRelationship.prototype.addCanonicalRecord = function(newRecord) {
-  if (this.canonicalMembers.has(newRecord)) { return;}
+  flushCanonical() {
+    //temporary fix to not remove newly created records if server returned null.
+    //TODO remove once we have proper diffing
+    if (this.inverseRecord && this.inverseRecord.isNew() && !this.canonicalState) {
+      return;
+    }
+    if (this.inverseRecord !== this.canonicalState) {
+      this.inverseRecord = this.canonicalState;
+      this.internalModel.notifyBelongsToChanged(this.key);
+    }
 
-  if (this.canonicalState) {
-    this.removeCanonicalRecord(this.canonicalState);
+    super.flushCanonical();
   }
 
-  this.canonicalState = newRecord;
-  this._super$addCanonicalRecord(newRecord);
-};
+  addRecord(newRecord) {
+    if (this.members.has(newRecord)) { return; }
+
+    assertPolymorphicType(this.internalModel, this.relationshipMeta, newRecord);
+
+    if (this.inverseRecord) {
+      this.removeRecord(this.inverseRecord);
+    }
 
-BelongsToRelationship.prototype._super$flushCanonical = Relationship.prototype.flushCanonical;
-BelongsToRelationship.prototype.flushCanonical = function() {
-  //temporary fix to not remove newly created records if server returned null.
-  //TODO remove once we have proper diffing
-  if (this.inverseRecord && this.inverseRecord.isNew() && !this.canonicalState) {
-    return;
+    this.inverseRecord = newRecord;
+    super.addRecord(newRecord);
+    this.internalModel.notifyBelongsToChanged(this.key);
   }
-  if (this.inverseRecord !== this.canonicalState) {
-    this.inverseRecord = this.canonicalState;
-    this.record.notifyBelongsToChanged(this.key);
+
+  setRecordPromise(newPromise) {
+    var content = newPromise.get && newPromise.get('content');
+    assert("You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.", content !== undefined);
+    this.setRecord(content ? content._internalModel : content);
   }
-  this._super$flushCanonical();
-};
 
-BelongsToRelationship.prototype._super$addRecord = Relationship.prototype.addRecord;
-BelongsToRelationship.prototype.addRecord = function(newRecord) {
-  if (this.members.has(newRecord)) { return;}
+  removeRecordFromOwn(record) {
+    if (!this.members.has(record)) { return;}
+    this.inverseRecord = null;
+    super.removeRecordFromOwn(record);
+    this.internalModel.notifyBelongsToChanged(this.key);
+  }
 
-  assertPolymorphicType(this.record, this.relationshipMeta, newRecord);
+  removeCanonicalRecordFromOwn(record) {
+    if (!this.canonicalMembers.has(record)) { return;}
+    this.canonicalState = null;
+    super.removeCanonicalRecordFromOwn(record);
+  }
 
-  if (this.inverseRecord) {
-    this.removeRecord(this.inverseRecord);
+  findRecord() {
+    if (this.inverseRecord) {
+      return this.store._findByInternalModel(this.inverseRecord);
+    } else {
+      return Ember.RSVP.Promise.resolve(null);
+    }
   }
 
-  this.inverseRecord = newRecord;
-  this._super$addRecord(newRecord);
-  this.record.notifyBelongsToChanged(this.key);
-};
-
-BelongsToRelationship.prototype.setRecordPromise = function(newPromise) {
-  var content = newPromise.get && newPromise.get('content');
-  assert("You passed in a promise that did not originate from an EmberData relationship. You can only pass promises that come from a belongsTo or hasMany relationship to the get call.", content !== undefined);
-  this.setRecord(content ? content._internalModel : content);
-};
-
-BelongsToRelationship.prototype._super$removeRecordFromOwn = Relationship.prototype.removeRecordFromOwn;
-BelongsToRelationship.prototype.removeRecordFromOwn = function(record) {
-  if (!this.members.has(record)) { return;}
-  this.inverseRecord = null;
-  this._super$removeRecordFromOwn(record);
-  this.record.notifyBelongsToChanged(this.key);
-};
-
-BelongsToRelationship.prototype._super$removeCanonicalRecordFromOwn = Relationship.prototype.removeCanonicalRecordFromOwn;
-BelongsToRelationship.prototype.removeCanonicalRecordFromOwn = function(record) {
-  if (!this.canonicalMembers.has(record)) { return;}
-  this.canonicalState = null;
-  this._super$removeCanonicalRecordFromOwn(record);
-};
-
-BelongsToRelationship.prototype.findRecord = function() {
-  if (this.inverseRecord) {
-    return this.store._findByInternalModel(this.inverseRecord);
-  } else {
-    return Ember.RSVP.Promise.resolve(null);
+  fetchLink() {
+    return this.store.findBelongsTo(this.internalModel, this.link, this.relationshipMeta).then((record) => {
+      if (record) {
+        this.addRecord(record);
+      }
+      return record;
+    });
   }
-};
 
-BelongsToRelationship.prototype.fetchLink = function() {
-  return this.store.findBelongsTo(this.record, this.link, this.relationshipMeta).then((record) => {
-    if (record) {
-      this.addRecord(record);
-    }
-    return record;
-  });
-};
-
-BelongsToRelationship.prototype.getRecord = function() {
-  //TODO(Igor) flushCanonical here once our syncing is not stupid
-  if (this.isAsync) {
-    var promise;
-    if (this.link) {
-      if (this.hasLoaded) {
-        promise = this.findRecord();
+  getRecord() {
+    //TODO(Igor) flushCanonical here once our syncing is not stupid
+    if (this.isAsync) {
+      var promise;
+      if (this.link) {
+        if (this.hasLoaded) {
+          promise = this.findRecord();
+        } else {
+          promise = this.findLink().then(() => this.findRecord());
+        }
       } else {
-        promise = this.findLink().then(() => this.findRecord());
+        promise = this.findRecord();
       }
+
+      return PromiseObject.create({
+        promise: promise,
+        content: this.inverseRecord ? this.inverseRecord.getRecord() : null
+      });
     } else {
-      promise = this.findRecord();
+      if (this.inverseRecord === null) {
+        return null;
+      }
+      var toReturn = this.inverseRecord.getRecord();
+      assert("You looked up the '" + this.key + "' relationship on a '" + this.internalModel.modelName + "' with id " + this.internalModel.id +  " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)", toReturn === null || !toReturn.get('isEmpty'));
+      return toReturn;
     }
+  }
 
-    return PromiseObject.create({
-      promise: promise,
-      content: this.inverseRecord ? this.inverseRecord.getRecord() : null
-    });
-  } else {
-    if (this.inverseRecord === null) {
-      return null;
+  reload() {
+    // TODO handle case when reload() is triggered multiple times
+
+    if (this.link) {
+      return this.fetchLink();
     }
-    var toReturn = this.inverseRecord.getRecord();
-    assert("You looked up the '" + this.key + "' relationship on a '" + this.record.modelName + "' with id " + this.record.id +  " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.belongsTo({ async: true })`)", toReturn === null || !toReturn.get('isEmpty'));
-    return toReturn;
-  }
-};
 
-BelongsToRelationship.prototype.reload = function() {
-  // TODO handle case when reload() is triggered multiple times
+    // reload record, if it is already loaded
+    if (this.inverseRecord && this.inverseRecord.hasRecord) {
+      return this.inverseRecord.record.reload();
+    }
 
-  if (this.link) {
-    return this.fetchLink();
+    return this.findRecord();
   }
 
-  // reload record, if it is already loaded
-  if (this.inverseRecord && this.inverseRecord.hasRecord) {
-    return this.inverseRecord.record.reload();
+  updateData(data) {
+    let internalModel = this.store._pushResourceIdentifier(this, data);
+    this.setCanonicalRecord(internalModel);
   }
-
-  return this.findRecord();
-};
-
-BelongsToRelationship.prototype.updateData = function(data) {
-  let internalModel = this.store._pushResourceIdentifier(this, data);
-  this.setCanonicalRecord(internalModel);
-};
+}
diff --git a/addon/-private/system/relationships/state/create.js b/addon/-private/system/relationships/state/create.js
index b5da724a921..6b6c1c67c31 100644
--- a/addon/-private/system/relationships/state/create.js
+++ b/addon/-private/system/relationships/state/create.js
@@ -3,18 +3,18 @@ import ManyRelationship from "ember-data/-private/system/relationships/state/has
 import BelongsToRelationship from "ember-data/-private/system/relationships/state/belongs-to";
 import EmptyObject from "ember-data/-private/system/empty-object";
 
-var get = Ember.get;
+const { get } = Ember;
 
 function shouldFindInverse(relationshipMeta) {
   let options = relationshipMeta.options;
   return !(options && options.inverse === null);
 }
 
-function createRelationshipFor(record, relationshipMeta, store) {
+function createRelationshipFor(internalModel, relationshipMeta, store) {
   let inverseKey;
   let inverse = null;
   if (shouldFindInverse(relationshipMeta)) {
-    inverse = record.type.inverseFor(relationshipMeta.key, store);
+    inverse = internalModel.type.inverseFor(relationshipMeta.key, store);
   }
 
   if (inverse) {
@@ -22,26 +22,36 @@ function createRelationshipFor(record, relationshipMeta, store) {
   }
 
   if (relationshipMeta.kind === 'hasMany') {
-    return new ManyRelationship(store, record, inverseKey, relationshipMeta);
+    return new ManyRelationship(store, internalModel, inverseKey, relationshipMeta);
   } else {
-    return new BelongsToRelationship(store, record, inverseKey, relationshipMeta);
+    return new BelongsToRelationship(store, internalModel, inverseKey, relationshipMeta);
   }
 }
 
-export default function Relationships(record) {
-  this.record = record;
-  this.initializedRelationships = new EmptyObject();
-}
+export default class Relationships {
+  constructor(internalModel) {
+    this.internalModel = internalModel;
+    this.initializedRelationships = new EmptyObject();
+  }
+
+  // TODO @runspired deprecate this as it was never truly a record instance
+  get record() {
+    return this.internalModel;
+  }
 
-Relationships.prototype.has = function(key) {
-  return !!this.initializedRelationships[key];
-};
+  has(key) {
+    return !!this.initializedRelationships[key];
+  }
+
+  get(key) {
+    let relationships = this.initializedRelationships;
+    let internalModel = this.internalModel;
+    let relationshipsByName = get(internalModel.type, 'relationshipsByName');
 
-Relationships.prototype.get = function(key) {
-  var relationships = this.initializedRelationships;
-  var relationshipsByName = get(this.record.type, 'relationshipsByName');
-  if (!relationships[key] && relationshipsByName.get(key)) {
-    relationships[key] = createRelationshipFor(this.record, relationshipsByName.get(key), this.record.store);
+    if (!relationships[key] && relationshipsByName.get(key)) {
+      relationships[key] = createRelationshipFor(internalModel, relationshipsByName.get(key), internalModel.store);
+    }
+
+    return relationships[key];
   }
-  return relationships[key];
-};
+}
diff --git a/addon/-private/system/relationships/state/has-many.js b/addon/-private/system/relationships/state/has-many.js
index 76f790eb6e0..881552024dd 100644
--- a/addon/-private/system/relationships/state/has-many.js
+++ b/addon/-private/system/relationships/state/has-many.js
@@ -6,234 +6,228 @@ import ManyArray from "ember-data/-private/system/many-array";
 
 import { assertPolymorphicType } from "ember-data/-private/debug";
 
-export default function ManyRelationship(store, record, inverseKey, relationshipMeta) {
-  this._super$constructor(store, record, inverseKey, relationshipMeta);
-  this.belongsToType = relationshipMeta.type;
-  this.canonicalState = [];
-  this.isPolymorphic = relationshipMeta.options.polymorphic;
-}
-
-ManyRelationship.prototype = Object.create(Relationship.prototype);
-ManyRelationship.prototype.getManyArray = function() {
-  if (!this._manyArray) {
-    this._manyArray = ManyArray.create({
-      canonicalState: this.canonicalState,
-      store: this.store,
-      relationship: this,
-      type: this.store.modelFor(this.belongsToType),
-      record: this.record,
-      meta: this.meta,
-      isPolymorphic: this.isPolymorphic
-    });
+export default class ManyRelationship extends Relationship {
+  constructor(store, record, inverseKey, relationshipMeta) {
+    super(store, record, inverseKey, relationshipMeta);
+    this.belongsToType = relationshipMeta.type;
+    this.canonicalState = [];
+    this.isPolymorphic = relationshipMeta.options.polymorphic;
+  }
+
+  getManyArray() {
+    if (!this._manyArray) {
+      this._manyArray = ManyArray.create({
+        canonicalState: this.canonicalState,
+        store: this.store,
+        relationship: this,
+        type: this.store.modelFor(this.belongsToType),
+        record: this.record,
+        meta: this.meta,
+        isPolymorphic: this.isPolymorphic
+      });
+    }
+    return this._manyArray;
   }
-  return this._manyArray;
-};
 
-ManyRelationship.prototype.constructor = ManyRelationship;
-ManyRelationship.prototype._super$constructor = Relationship;
-
-ManyRelationship.prototype.destroy = function() {
-  if (this._manyArray) {
-    this._manyArray.destroy();
+  destroy() {
+    if (this._manyArray) {
+      this._manyArray.destroy();
+    }
   }
-};
 
-ManyRelationship.prototype._super$updateMeta = Relationship.prototype.updateMeta;
-ManyRelationship.prototype.updateMeta = function(meta) {
-  this._super$updateMeta(meta);
-  if (this._manyArray) {
-    this._manyArray.set('meta', meta);
+  updateMeta(meta) {
+    super.updateMeta(meta);
+    if (this._manyArray) {
+      this._manyArray.set('meta', meta);
+    }
   }
-};
 
-ManyRelationship.prototype._super$addCanonicalRecord = Relationship.prototype.addCanonicalRecord;
-ManyRelationship.prototype.addCanonicalRecord = function(record, idx) {
-  if (this.canonicalMembers.has(record)) {
-    return;
-  }
-  if (idx !== undefined) {
-    this.canonicalState.splice(idx, 0, record);
-  } else {
-    this.canonicalState.push(record);
+  addCanonicalRecord(record, idx) {
+    if (this.canonicalMembers.has(record)) {
+      return;
+    }
+    if (idx !== undefined) {
+      this.canonicalState.splice(idx, 0, record);
+    } else {
+      this.canonicalState.push(record);
+    }
+    super.addCanonicalRecord(record, idx);
   }
-  this._super$addCanonicalRecord(record, idx);
-};
 
-ManyRelationship.prototype._super$addRecord = Relationship.prototype.addRecord;
-ManyRelationship.prototype.addRecord = function(record, idx) {
-  if (this.members.has(record)) {
-    return;
+  addRecord(record, idx) {
+    if (this.members.has(record)) {
+      return;
+    }
+    super.addRecord(record, idx);
+    // make lazy later
+    this.getManyArray().internalAddRecords([record], idx);
   }
-  this._super$addRecord(record, idx);
-  // make lazy later
-  this.getManyArray().internalAddRecords([record], idx);
-};
 
-ManyRelationship.prototype._super$removeCanonicalRecordFromOwn = Relationship.prototype.removeCanonicalRecordFromOwn;
-ManyRelationship.prototype.removeCanonicalRecordFromOwn = function(record, idx) {
-  var i = idx;
-  if (!this.canonicalMembers.has(record)) {
-    return;
-  }
-  if (i === undefined) {
-    i = this.canonicalState.indexOf(record);
-  }
-  if (i > -1) {
-    this.canonicalState.splice(i, 1);
+  removeCanonicalRecordFromOwn(record, idx) {
+    var i = idx;
+    if (!this.canonicalMembers.has(record)) {
+      return;
+    }
+    if (i === undefined) {
+      i = this.canonicalState.indexOf(record);
+    }
+    if (i > -1) {
+      this.canonicalState.splice(i, 1);
+    }
+    super.removeCanonicalRecordFromOwn(record, idx);
   }
-  this._super$removeCanonicalRecordFromOwn(record, idx);
-};
 
-ManyRelationship.prototype._super$flushCanonical = Relationship.prototype.flushCanonical;
-ManyRelationship.prototype.flushCanonical = function() {
-  if (this._manyArray) {
-    this._manyArray.flushCanonical();
+  flushCanonical() {
+    if (this._manyArray) {
+      this._manyArray.flushCanonical();
+    }
+    super.flushCanonical();
   }
-  this._super$flushCanonical();
-};
 
-ManyRelationship.prototype._super$removeRecordFromOwn = Relationship.prototype.removeRecordFromOwn;
-ManyRelationship.prototype.removeRecordFromOwn = function(record, idx) {
-  if (!this.members.has(record)) {
-    return;
-  }
-  this._super$removeRecordFromOwn(record, idx);
-  let manyArray = this.getManyArray();
-  if (idx !== undefined) {
-    //TODO(Igor) not used currently, fix
-    manyArray.currentState.removeAt(idx);
-  } else {
-    manyArray.internalRemoveRecords([record]);
+  removeRecordFromOwn(record, idx) {
+    if (!this.members.has(record)) {
+      return;
+    }
+    super.removeRecordFromOwn(record, idx);
+    let manyArray = this.getManyArray();
+    if (idx !== undefined) {
+      //TODO(Igor) not used currently, fix
+      manyArray.currentState.removeAt(idx);
+    } else {
+      manyArray.internalRemoveRecords([record]);
+    }
   }
-};
 
-ManyRelationship.prototype.notifyRecordRelationshipAdded = function(record, idx) {
-  assertPolymorphicType(this.record, this.relationshipMeta, record);
+  notifyRecordRelationshipAdded(record, idx) {
+    assertPolymorphicType(this.record, this.relationshipMeta, record);
 
-  this.record.notifyHasManyAdded(this.key, record, idx);
-};
+    this.record.notifyHasManyAdded(this.key, record, idx);
+  }
 
-ManyRelationship.prototype.reload = function() {
-  let manyArray = this.getManyArray();
-  let manyArrayLoadedState = manyArray.get('isLoaded');
+  reload() {
+    let manyArray = this.getManyArray();
+    let manyArrayLoadedState = manyArray.get('isLoaded');
 
-  if (this._loadingPromise) {
-    if (this._loadingPromise.get('isPending')) {
-      return this._loadingPromise;
-    }
-    if (this._loadingPromise.get('isRejected')) {
-      manyArray.set('isLoaded', manyArrayLoadedState);
+    if (this._loadingPromise) {
+      if (this._loadingPromise.get('isPending')) {
+        return this._loadingPromise;
+      }
+      if (this._loadingPromise.get('isRejected')) {
+        manyArray.set('isLoaded', manyArrayLoadedState);
+      }
     }
-  }
 
-  if (this.link) {
-    this._loadingPromise = promiseManyArray(this.fetchLink(), 'Reload with link');
-    return this._loadingPromise;
-  } else {
-    this._loadingPromise = promiseManyArray(this.store._scheduleFetchMany(manyArray.currentState).then(() => manyArray), 'Reload with ids');
-    return this._loadingPromise;
+    if (this.link) {
+      this._loadingPromise = promiseManyArray(this.fetchLink(), 'Reload with link');
+      return this._loadingPromise;
+    } else {
+      this._loadingPromise = promiseManyArray(this.store._scheduleFetchMany(manyArray.currentState).then(() => manyArray), 'Reload with ids');
+      return this._loadingPromise;
+    }
   }
-};
 
-ManyRelationship.prototype.computeChanges = function(records) {
-  var members = this.canonicalMembers;
-  var recordsToRemove = [];
-  var length;
-  var record;
-  var i;
+  computeChanges(records) {
+    var members = this.canonicalMembers;
+    var recordsToRemove = [];
+    var length;
+    var record;
+    var i;
 
-  records = setForArray(records);
+    records = setForArray(records);
 
-  members.forEach(function(member) {
-    if (records.has(member)) { return; }
+    members.forEach(function(member) {
+      if (records.has(member)) { return; }
 
-    recordsToRemove.push(member);
-  });
+      recordsToRemove.push(member);
+    });
 
-  this.removeCanonicalRecords(recordsToRemove);
+    this.removeCanonicalRecords(recordsToRemove);
+
+    // Using records.toArray() since currently using
+    // removeRecord can modify length, messing stuff up
+    // forEach since it directly looks at "length" each
+    // iteration
+    records = records.toArray();
+    length = records.length;
+    for (i = 0; i < length; i++) {
+      record = records[i];
+      this.removeCanonicalRecord(record);
+      this.addCanonicalRecord(record, i);
+    }
+  }
 
-  // Using records.toArray() since currently using
-  // removeRecord can modify length, messing stuff up
-  // forEach since it directly looks at "length" each
-  // iteration
-  records = records.toArray();
-  length = records.length;
-  for (i = 0; i < length; i++) {
-    record = records[i];
-    this.removeCanonicalRecord(record);
-    this.addCanonicalRecord(record, i);
+  fetchLink() {
+    return this.store.findHasMany(this.record, this.link, this.relationshipMeta).then((records) => {
+      if (records.hasOwnProperty('meta')) {
+        this.updateMeta(records.meta);
+      }
+      this.store._backburner.join(() => {
+        this.updateRecordsFromAdapter(records);
+        this.getManyArray().set('isLoaded', true);
+      });
+      return this.getManyArray();
+    });
   }
-};
 
-ManyRelationship.prototype.fetchLink = function() {
-  return this.store.findHasMany(this.record, this.link, this.relationshipMeta).then((records) => {
-    if (records.hasOwnProperty('meta')) {
-      this.updateMeta(records.meta);
+  findRecords() {
+    let manyArray = this.getManyArray();
+    let array = manyArray.toArray();
+    let internalModels = new Array(array.length);
+
+    for (let i = 0; i < array.length; i++) {
+      internalModels[i] = array[i]._internalModel;
     }
-    this.store._backburner.join(() => {
-      this.updateRecordsFromAdapter(records);
-      this.getManyArray().set('isLoaded', true);
+
+    //TODO CLEANUP
+    return this.store.findMany(internalModels).then(() => {
+      if (!manyArray.get('isDestroyed')) {
+        //Goes away after the manyArray refactor
+        manyArray.set('isLoaded', true);
+      }
+      return manyArray;
     });
-    return this.getManyArray();
-  });
-};
-
-ManyRelationship.prototype.findRecords = function() {
-  let manyArray = this.getManyArray()
-  let array = manyArray.toArray();
-  let internalModels = new Array(array.length);
-
-  for (let i = 0; i < array.length; i++) {
-    internalModels[i] = array[i]._internalModel;
-  }
-
-  //TODO CLEANUP
-  return this.store.findMany(internalModels).then(() => {
-    if (!manyArray.get('isDestroyed')) {
-      //Goes away after the manyArray refactor
-      manyArray.set('isLoaded', true);
-    }
-    return manyArray;
-  });
-};
-ManyRelationship.prototype.notifyHasManyChanged = function() {
-  this.record.notifyHasManyAdded(this.key);
-};
-
-ManyRelationship.prototype.getRecords = function() {
-  //TODO(Igor) sync server here, once our syncing is not stupid
-  let manyArray = this.getManyArray();
-  if (this.isAsync) {
-    var promise;
-    if (this.link) {
-      if (this.hasLoaded) {
-        promise = this.findRecords();
+  }
+
+  notifyHasManyChanged() {
+    this.record.notifyHasManyAdded(this.key);
+  }
+
+  getRecords() {
+    //TODO(Igor) sync server here, once our syncing is not stupid
+    let manyArray = this.getManyArray();
+    if (this.isAsync) {
+      var promise;
+      if (this.link) {
+        if (this.hasLoaded) {
+          promise = this.findRecords();
+        } else {
+          promise = this.findLink().then(() => this.findRecords());
+        }
       } else {
-        promise = this.findLink().then(() => this.findRecords());
+        promise = this.findRecords();
       }
+      this._loadingPromise = PromiseManyArray.create({
+        content: manyArray,
+        promise: promise
+      });
+      return this._loadingPromise;
     } else {
-      promise = this.findRecords();
-    }
-    this._loadingPromise = PromiseManyArray.create({
-      content: manyArray,
-      promise: promise
-    });
-    return this._loadingPromise;
-  } else {
-    assert("You looked up the '" + this.key + "' relationship on a '" + this.record.type.modelName + "' with id " + this.record.id +  " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.hasMany({ async: true })`)", manyArray.isEvery('isEmpty', false));
+      assert("You looked up the '" + this.key + "' relationship on a '" + this.record.type.modelName + "' with id " + this.record.id +  " but some of the associated records were not loaded. Either make sure they are all loaded together with the parent record, or specify that the relationship is async (`DS.hasMany({ async: true })`)", manyArray.isEvery('isEmpty', false));
 
-    //TODO(Igor) WTF DO I DO HERE?
-    if (!manyArray.get('isDestroyed')) {
-      manyArray.set('isLoaded', true);
+      //TODO(Igor) WTF DO I DO HERE?
+      // TODO @runspired equal WTFs to Igor
+      if (!manyArray.get('isDestroyed')) {
+        manyArray.set('isLoaded', true);
+      }
+      return manyArray;
     }
-    return manyArray;
   }
-};
 
-ManyRelationship.prototype.updateData = function(data) {
-  let internalModels = this.store._pushResourceIdentifiers(this, data);
-  this.updateRecordsFromAdapter(internalModels);
-};
+  updateData(data) {
+    let internalModels = this.store._pushResourceIdentifiers(this, data);
+    this.updateRecordsFromAdapter(internalModels);
+  }
+}
 
 function setForArray(array) {
   var set = new OrderedSet();
diff --git a/addon/-private/system/relationships/state/relationship.js b/addon/-private/system/relationships/state/relationship.js
index 7266ef6cb28..e361526bc9d 100644
--- a/addon/-private/system/relationships/state/relationship.js
+++ b/addon/-private/system/relationships/state/relationship.js
@@ -53,35 +53,42 @@ const {
   'updateRecordsFromAdapter'
 );
 
-export default function Relationship(store, record, inverseKey, relationshipMeta) {
-  heimdall.increment(newRelationship);
-  var async = relationshipMeta.options.async;
-  this.members = new OrderedSet();
-  this.canonicalMembers = new OrderedSet();
-  this.store = store;
-  this.key = relationshipMeta.key;
-  this.inverseKey = inverseKey;
-  this.record = record;
-  this.isAsync = typeof async === 'undefined' ? true : async;
-  this.relationshipMeta = relationshipMeta;
-  //This probably breaks for polymorphic relationship in complex scenarios, due to
-  //multiple possible modelNames
-  this.inverseKeyForImplicit = this.record.constructor.modelName + this.key;
-  this.linkPromise = null;
-  this.meta = null;
-  this.hasData = false;
-  this.hasLoaded = false;
-}
+export default class Relationship {
+  constructor(store, internalModel, inverseKey, relationshipMeta) {
+    heimdall.increment(newRelationship);
+    var async = relationshipMeta.options.async;
+    this.members = new OrderedSet();
+    this.canonicalMembers = new OrderedSet();
+    this.store = store;
+    this.key = relationshipMeta.key;
+    this.inverseKey = inverseKey;
+    this.internalModel = internalModel;
+    this.isAsync = typeof async === 'undefined' ? true : async;
+    this.relationshipMeta = relationshipMeta;
+    //This probably breaks for polymorphic relationship in complex scenarios, due to
+    //multiple possible modelNames
+    this.inverseKeyForImplicit = this.internalModel.modelName + this.key;
+    this.linkPromise = null;
+    this.meta = null;
+    this.hasData = false;
+    this.hasLoaded = false;
+  }
 
-Relationship.prototype = {
-  constructor: Relationship,
+  // TODO @runspired deprecate this as it was never truly a record instance
+  get record() {
+    return this.internalModel;
+  }
 
-  destroy() { },
+  get parentType() {
+    return this.internalModel.modelName;
+  }
+
+  destroy() { }
 
   updateMeta(meta) {
     heimdall.increment(updateMeta);
     this.meta = meta;
-  },
+  }
 
   clear() {
     heimdall.increment(clear);
@@ -92,12 +99,12 @@ Relationship.prototype = {
       member = members[0];
       this.removeRecord(member);
     }
-  },
+  }
 
   removeRecords(records) {
     heimdall.increment(removeRecords);
     records.forEach((record) => this.removeRecord(record));
-  },
+  }
 
   addRecords(records, idx) {
     heimdall.increment(addRecords);
@@ -107,7 +114,7 @@ Relationship.prototype = {
         idx++;
       }
     });
-  },
+  }
 
   addCanonicalRecords(records, idx) {
     heimdall.increment(addCanonicalRecords);
@@ -118,7 +125,7 @@ Relationship.prototype = {
         this.addCanonicalRecord(records[i]);
       }
     }
-  },
+  }
 
   addCanonicalRecord(record, idx) {
     heimdall.increment(addCanonicalRecord);
@@ -135,7 +142,7 @@ Relationship.prototype = {
     }
     this.flushCanonicalLater();
     this.setHasData(true);
-  },
+  }
 
   removeCanonicalRecords(records, idx) {
     heimdall.increment(removeCanonicalRecords);
@@ -146,7 +153,7 @@ Relationship.prototype = {
         this.removeCanonicalRecord(records[i]);
       }
     }
-  },
+  }
 
   removeCanonicalRecord(record, idx) {
     heimdall.increment(removeCanonicalRecord);
@@ -161,7 +168,7 @@ Relationship.prototype = {
       }
     }
     this.flushCanonicalLater();
-  },
+  }
 
   addRecord(record, idx) {
     heimdall.increment(addRecord);
@@ -179,7 +186,7 @@ Relationship.prototype = {
       this.record.updateRecordArraysLater();
     }
     this.setHasData(true);
-  },
+  }
 
   removeRecord(record) {
     heimdall.increment(removeRecord);
@@ -193,7 +200,7 @@ Relationship.prototype = {
         }
       }
     }
-  },
+  }
 
   removeRecordFromInverse(record) {
     heimdall.increment(removeRecordFromInverse);
@@ -202,14 +209,14 @@ Relationship.prototype = {
     if (inverseRelationship) {
       inverseRelationship.removeRecordFromOwn(this.record);
     }
-  },
+  }
 
   removeRecordFromOwn(record) {
     heimdall.increment(removeRecordFromOwn);
     this.members.delete(record);
     this.notifyRecordRelationshipRemoved(record);
     this.record.updateRecordArrays();
-  },
+  }
 
   removeCanonicalRecordFromInverse(record) {
     heimdall.increment(removeCanonicalRecordFromInverse);
@@ -218,13 +225,13 @@ Relationship.prototype = {
     if (inverseRelationship) {
       inverseRelationship.removeCanonicalRecordFromOwn(this.record);
     }
-  },
+  }
 
   removeCanonicalRecordFromOwn(record) {
     heimdall.increment(removeCanonicalRecordFromOwn);
     this.canonicalMembers.delete(record);
     this.flushCanonicalLater();
-  },
+  }
 
   flushCanonical() {
     heimdall.increment(flushCanonical);
@@ -232,17 +239,17 @@ Relationship.prototype = {
     //a hack for not removing new records
     //TODO remove once we have proper diffing
     var newRecords = [];
-    for (var i=0; i<this.members.list.length; i++) {
+    for (var i = 0; i < this.members.list.length; i++) {
       if (this.members.list[i].isNew()) {
         newRecords.push(this.members.list[i]);
       }
     }
     //TODO(Igor) make this less abysmally slow
     this.members = this.canonicalMembers.copy();
-    for (i=0; i<newRecords.length; i++) {
+    for (i = 0; i < newRecords.length; i++) {
       this.members.add(newRecords[i]);
     }
-  },
+  }
 
   flushCanonicalLater() {
     heimdall.increment(flushCanonicalLater);
@@ -251,7 +258,7 @@ Relationship.prototype = {
     }
     this.willSync = true;
     this.store._backburner.join(() => this.store._backburner.schedule('syncRelationships', this, this.flushCanonical));
-  },
+  }
 
   updateLink(link) {
     heimdall.increment(updateLink);
@@ -263,7 +270,7 @@ Relationship.prototype = {
     this.link = link;
     this.linkPromise = null;
     this.record.notifyPropertyChange(this.key);
-  },
+  }
 
   findLink() {
     heimdall.increment(findLink);
@@ -274,55 +281,55 @@ Relationship.prototype = {
       this.linkPromise = promise;
       return promise.then((result) => result);
     }
-  },
+  }
 
   updateRecordsFromAdapter(records) {
     heimdall.increment(updateRecordsFromAdapter);
     //TODO(Igor) move this to a proper place
     //TODO Once we have adapter support, we need to handle updated and canonical changes
     this.computeChanges(records);
-  },
+  }
 
-  notifyRecordRelationshipAdded() { },
-  notifyRecordRelationshipRemoved() { },
+  notifyRecordRelationshipAdded() { }
+  notifyRecordRelationshipRemoved() { }
 
   /*
-    `hasData` for a relationship is a flag to indicate if we consider the
-    content of this relationship "known". Snapshots uses this to tell the
-    difference between unknown (`undefined`) or empty (`null`). The reason for
-    this is that we wouldn't want to serialize unknown relationships as `null`
-    as that might overwrite remote state.
-
-    All relationships for a newly created (`store.createRecord()`) are
-    considered known (`hasData === true`).
+   `hasData` for a relationship is a flag to indicate if we consider the
+   content of this relationship "known". Snapshots uses this to tell the
+   difference between unknown (`undefined`) or empty (`null`). The reason for
+   this is that we wouldn't want to serialize unknown relationships as `null`
+   as that might overwrite remote state.
+
+   All relationships for a newly created (`store.createRecord()`) are
+   considered known (`hasData === true`).
    */
   setHasData(value) {
     heimdall.increment(setHasData);
     this.hasData = value;
-  },
+  }
 
   /*
-    `hasLoaded` is a flag to indicate if we have gotten data from the adapter or
-    not when the relationship has a link.
+   `hasLoaded` is a flag to indicate if we have gotten data from the adapter or
+   not when the relationship has a link.
 
-    This is used to be able to tell when to fetch the link and when to return
-    the local data in scenarios where the local state is considered known
-    (`hasData === true`).
+   This is used to be able to tell when to fetch the link and when to return
+   the local data in scenarios where the local state is considered known
+   (`hasData === true`).
 
-    Updating the link will automatically set `hasLoaded` to `false`.
+   Updating the link will automatically set `hasLoaded` to `false`.
    */
   setHasLoaded(value) {
     heimdall.increment(setHasLoaded);
     this.hasLoaded = value;
-  },
+  }
 
   /*
-    `push` for a relationship allows the store to push a JSON API Relationship
-    Object onto the relationship. The relationship will then extract and set the
-    meta, data and links of that relationship.
+   `push` for a relationship allows the store to push a JSON API Relationship
+   Object onto the relationship. The relationship will then extract and set the
+   meta, data and links of that relationship.
 
-    `push` use `updateMeta`, `updateData` and `updateLink` to update the state
-    of the relationship.
+   `push` use `updateMeta`, `updateData` and `updateLink` to update the state
+   of the relationship.
    */
   push(payload) {
     heimdall.increment(push);
@@ -348,16 +355,16 @@ Relationship.prototype = {
     }
 
     /*
-      Data being pushed into the relationship might contain only data or links,
-      or a combination of both.
+     Data being pushed into the relationship might contain only data or links,
+     or a combination of both.
 
-      If we got data we want to set both hasData and hasLoaded to true since
-      this would indicate that we should prefer the local state instead of
-      trying to fetch the link or call findRecord().
+     If we got data we want to set both hasData and hasLoaded to true since
+     this would indicate that we should prefer the local state instead of
+     trying to fetch the link or call findRecord().
 
-      If we have no data but a link is present we want to set hasLoaded to false
-      without modifying the hasData flag. This will ensure we fetch the updated
-      link next time the relationship is accessed.
+     If we have no data but a link is present we want to set hasLoaded to false
+     without modifying the hasData flag. This will ensure we fetch the updated
+     link next time the relationship is accessed.
      */
     if (hasData) {
       this.setHasData(true);
@@ -365,7 +372,7 @@ Relationship.prototype = {
     } else if (hasLink) {
       this.setHasLoaded(false);
     }
-  },
+  }
 
   updateData() {}
-};
+}