Skip to content

Commit

Permalink
Add relationship interfaces and deprecate bunch of cache/model methods
Browse files Browse the repository at this point in the history
  • Loading branch information
tchak committed Dec 27, 2019
1 parent 03c0302 commit 3c22ccf
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 72 deletions.
21 changes: 18 additions & 3 deletions addon/-private/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,21 @@ export default class Cache {
relationship: string
): Model | null | undefined {
deprecate(
'`Cache#retrieveRelatedRecord(identity, relationship)` is deprecated, use `Cache#peekRelatedRecord(identity, relationship)`.'
'`Cache#retrieveRelatedRecord(identity, relationship)` is deprecated, use `Cache#peekRecord(identity).hasOne(relationship).value`.'
);
return this.peekRelatedRecord(identity, relationship);
}

/**
* @deprecated
*/
peekRelatedRecord(
identity: RecordIdentity,
relationship: string
): Model | null | undefined {
deprecate(
'`Cache#peekRelatedRecord(identity, relationship)` is deprecated, use `Cache#peekRecord(identity).hasOne(relationship).value`.'
);
const relatedRecord = this._sourceCache.getRelatedRecordSync(
identity,
relationship
Expand All @@ -192,15 +198,21 @@ export default class Cache {
relationship: string
): Model[] | undefined {
deprecate(
'`Cache#retrieveRelatedRecords(identity, relationship)` is deprecated, use `Cache#peekRelatedRecords(identity, relationship)`.'
'`Cache#retrieveRelatedRecords(identity, relationship)` is deprecated, use `Cache#peekRecord(identity).hasMany(relationship).value`.'
);
return this.peekRelatedRecords(identity, relationship);
}

/**
* @deprecated
*/
peekRelatedRecords(
identity: RecordIdentity,
relationship: string
): Model[] | undefined {
deprecate(
'`Cache#peekRelatedRecords(identity, relationship)` is deprecated, use `Cache#peekRecord(identity).hasMany(relationship).value`.'
);
const relatedRecords = this._sourceCache.getRelatedRecordsSync(
identity,
relationship
Expand Down Expand Up @@ -261,9 +273,12 @@ export default class Cache {
}
}

/**
* @deprecated
*/
findAll(type: string, options?: object): Model[] {
deprecate(
'`Cache.findAll(type)` is deprecated, use `Cache.findRecords(type)`.'
'`Cache#findAll(type)` is deprecated, use `Cache#findRecords(type)`.'
);
return this.findRecords(type, options);
}
Expand Down
22 changes: 21 additions & 1 deletion addon/-private/fields/has-many.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
import { computed } from '@ember/object';
import { Dict } from '@orbit/utils';
import { RecordIdentity } from '@orbit/data';
import Orbit from '@orbit/core';

const { deprecate } = Orbit;

export default function(type: string, options: Dict<unknown> = {}) {
options.kind = 'hasMany';
options.type = type;

return computed({
get(key) {
return this.getRelatedRecords(key);
const records = this.hasMany(key).value;

records.pushObject = (record: RecordIdentity) => {
deprecate(
'`HasMany#pushObject(record)` is deprecated, use `Model#hasMany(relationship).add(record)`.'
);
return this.hasMany(key).add(record);
};

records.removeObject = (record: RecordIdentity) => {
deprecate(
'`HasMany#removeObject(record)` is deprecated, use `Model#hasMany(relationship).remove(record)`.'
);
return this.hasMany(key).remove(record);
};

return records;
}
})
.meta({
Expand Down
6 changes: 3 additions & 3 deletions addon/-private/fields/has-one.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ export default function(type: string, options: Dict<unknown> = {}) {

return computed({
get(key) {
return this.getRelatedRecord(key);
return this.hasOne(key).value;
},
set(key, value) {
const oldValue = this.getRelatedRecord(key);
const oldValue = this.hasOne(key).value;

if (value !== oldValue) {
this.replaceRelatedRecord(key, value);
this.hasOne(key).replace(value);
}

return value;
Expand Down
86 changes: 59 additions & 27 deletions addon/-private/model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import EmberObject from '@ember/object';
import Orbit from '@orbit/core';
import { Dict } from '@orbit/utils';
import {
Record,
Expand All @@ -8,22 +9,21 @@ import {
RelationshipDefinition
} from '@orbit/data';

import HasMany from './relationships/has-many';
const { deprecate } = Orbit;

import { HasOneRelationship, HasManyRelationship } from './relationships';
import Store from './store';

export interface ModelSettings {
identity: RecordIdentity;
}

interface HasManyContract {
invalidate(): void;
}

export default class Model extends EmberObject {
identity!: RecordIdentity;

private _store?: Store;
private _relatedRecords: Dict<HasManyContract> = {};
private _hasManyRelationships: Dict<HasManyRelationship> = {};
private _hasOneRelationships: Dict<HasOneRelationship> = {};

get id(): string {
return this.identity.id;
Expand Down Expand Up @@ -56,6 +56,28 @@ export default class Model extends EmberObject {
);
}

hasMany(name: string): HasManyRelationship {
let relationship = this._hasManyRelationships[name];
if (!relationship) {
this._hasManyRelationships[name] = relationship = new HasManyRelationship(
this,
name
);
}
return relationship;
}

hasOne(name: string): HasOneRelationship {
let relationship = this._hasOneRelationships[name];
if (!relationship) {
this._hasOneRelationships[name] = relationship = new HasOneRelationship(
this,
name
);
}
return relationship;
}

getAttribute(field: string): any {
return this.store.cache.peekAttribute(this.identity, field);
}
Expand All @@ -71,15 +93,27 @@ export default class Model extends EmberObject {
);
}

/**
* @deprecated
*/
getRelatedRecord(relationship: string): Record | null | undefined {
deprecate(
'`Model#getRelatedRecord(relationship)` is deprecated, use `Model#hasOne(relationship).value`.'
);
return this.store.cache.peekRelatedRecord(this.identity, relationship);
}

/**
* @deprecated
*/
async replaceRelatedRecord(
relationship: string,
relatedRecord: Model | null,
options?: object
): Promise<void> {
deprecate(
'`Model#replaceRelatedRecord(relationship, record)` is deprecated, use `Model#hasOne(relationship).replace(record)`.'
);
await this.store.update(
t =>
t.replaceRelatedRecord(
Expand All @@ -91,42 +125,34 @@ export default class Model extends EmberObject {
);
}

getRelatedRecords(relationship: string) {
this._relatedRecords = this._relatedRecords || {};

if (!this._relatedRecords[relationship]) {
this._relatedRecords[relationship] = HasMany.create({
getContent: () =>
this.store.cache.peekRelatedRecords(this.identity, relationship),
addToContent: (record: Model): Promise<void> => {
return this.addToRelatedRecords(relationship, record);
},
removeFromContent: (record: Model): Promise<void> => {
return this.removeFromRelatedRecords(relationship, record);
}
});
}
this._relatedRecords[relationship].invalidate();

return this._relatedRecords[relationship];
}

/**
* @deprecated
*/
async addToRelatedRecords(
relationship: string,
record: Model,
options?: object
): Promise<void> {
deprecate(
'`Model#addToRelatedRecords(relationship, record)` is deprecated, use `Model#hasMany(relationship).add(record)`.'
);
await this.store.update(
t => t.addToRelatedRecords(this.identity, relationship, record.identity),
options
);
}

/**
* @deprecated
*/
async removeFromRelatedRecords(
relationship: string,
record: Model,
options?: object
): Promise<void> {
deprecate(
'`Model#removeFromRelatedRecords(relationship, record)` is deprecated, use `Model#hasMany(relationship).remove(record)`.'
);
await this.store.update(
t =>
t.removeFromRelatedRecords(
Expand All @@ -138,10 +164,16 @@ export default class Model extends EmberObject {
);
}

/**
* @deprecated
*/
async replaceAttributes(
properties: Dict<unknown> = {},
options?: object
): Promise<void> {
deprecate(
'`Model#replaceAttributes(properties)` is deprecated, use `Model#update(properties)`.'
);
const keys = Object.keys(properties);
await this.store
.update(
Expand Down Expand Up @@ -176,7 +208,7 @@ export default class Model extends EmberObject {
}
}

private get store(): Store {
get store(): Store {
if (!this._store) {
throw new Error('record has been removed from Store');
}
Expand Down
95 changes: 95 additions & 0 deletions addon/-private/relationships.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { RecordIdentity, cloneRecordIdentity } from '@orbit/data';

import Model from './model';

export class Relationship {
readonly name: string;
readonly owner: Model;

constructor(owner: Model, name: string) {
this.name = name;
this.owner = owner;
}
}

export class HasOneRelationship extends Relationship {
get value(): Model | null {
return this.owner.store.cache.query(q =>
q.findRelatedRecord(this.owner.identity, this.name)
) as Model | null;
}

load(options?: object): Promise<Model | null> {
return this.owner.store.query(
q => q.findRelatedRecord(this.owner.identity, this.name),
options
);
}

async replace(record: RecordIdentity, options?: object): Promise<void> {
await this.owner.store.update(
t =>
t.replaceRelatedRecord(
this.owner.identity,
this.name,
record ? cloneRecordIdentity(record) : null
),
options
);
}
}

export class HasManyRelationship extends Relationship {
get value(): Model[] {
return this.owner.store.cache.query(q =>
q.findRelatedRecords(this.owner.identity, this.name)
) as Model[];
}

get ids(): string[] {
return this.value.map((record: RecordIdentity) => record.id);
}

load(options?: object): Promise<Model[]> {
return this.owner.store.query(
q => q.findRelatedRecords(this.owner.identity, this.name),
options
);
}

async add(record: RecordIdentity, options?: object): Promise<void> {
await this.owner.store.update(
t =>
t.addToRelatedRecords(
this.owner.identity,
this.name,
cloneRecordIdentity(record)
),
options
);
}

async remove(record: RecordIdentity, options?: object): Promise<void> {
await this.owner.store.update(
t =>
t.removeFromRelatedRecords(
this.owner.identity,
this.name,
cloneRecordIdentity(record)
),
options
);
}

async replace(records: RecordIdentity[], options?: object): Promise<void> {
await this.owner.store.update(
t =>
t.replaceRelatedRecords(
this.owner.identity,
this.name,
records.map(record => cloneRecordIdentity(record))
),
options
);
}
}
11 changes: 0 additions & 11 deletions addon/-private/relationships/has-many.js

This file was deleted.

Loading

0 comments on commit 3c22ccf

Please sign in to comment.