Skip to content

Commit

Permalink
polish
Browse files Browse the repository at this point in the history
  • Loading branch information
runspired committed Apr 21, 2021
1 parent 32bf2f7 commit 4700c60
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 35 deletions.
26 changes: 16 additions & 10 deletions packages/model/addon/-private/belongs-to.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { assert, inspect, warn } from '@ember/debug';
import { computed } from '@ember/object';
import { DEBUG } from '@glimmer/env';

import { normalizeModelName } from '@ember-data/store';

import { computedMacroWithOptionalParams } from './util';

/**
Expand Down Expand Up @@ -112,20 +110,28 @@ import { computedMacroWithOptionalParams } from './util';
@return {Ember.computed} relationship
*/
function belongsTo(modelName, options) {
let opts, userEnteredModelName;
if (typeof modelName === 'object') {
opts = modelName;
userEnteredModelName = undefined;
} else {
opts = options;
userEnteredModelName = modelName;
}

assert(
'The first argument to belongsTo must be a string representing a model type key, not an instance of ' +
inspect(modelName) +
inspect(userEnteredModelName) +
". E.g., to define a relation to the Person model, use belongsTo('person')",
typeof modelName !== 'string'
typeof userEnteredModelName === 'string' || typeof userEnteredModelName === 'undefined'
);

modelName = normalizeModelName(modelName);
options = options || {};
opts = opts || {};

let meta = {
type: modelName,
type: userEnteredModelName,
isRelationship: true,
options,
options: opts,
kind: 'belongsTo',
name: 'Belongs To',
key: null,
Expand All @@ -139,7 +145,7 @@ function belongsTo(modelName, options) {
`'${key}' is a reserved property name on instances of classes extending Model. Please choose a different property name for your belongsTo on ${this.constructor.toString()}`
);
}
if (Object.prototype.hasOwnProperty.call(options, 'serialize')) {
if (Object.prototype.hasOwnProperty.call(opts, 'serialize')) {
warn(
`You provided a serialize option on the "${key}" property in the "${this._internalModel.modelName}" class, this belongs in the serializer. See Serializer and it's implementations https://api.emberjs.com/ember-data/release/classes/Serializer`,
false,
Expand All @@ -149,7 +155,7 @@ function belongsTo(modelName, options) {
);
}

if (Object.prototype.hasOwnProperty.call(options, 'embedded')) {
if (Object.prototype.hasOwnProperty.call(opts, 'embedded')) {
warn(
`You provided an embedded option on the "${key}" property in the "${this._internalModel.modelName}" class, this belongs in the serializer. See EmbeddedRecordsMixin https://api.emberjs.com/ember-data/release/classes/EmbeddedRecordsMixin`,
false,
Expand Down
12 changes: 6 additions & 6 deletions packages/model/addon/-private/has-many.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import { assert, inspect } from '@ember/debug';
import { computed } from '@ember/object';
import { DEBUG } from '@glimmer/env';

import { singularize } from 'ember-inflector';

import { normalizeModelName } from '@ember-data/store';

import { computedMacroWithOptionalParams } from './util';

/**
Expand Down Expand Up @@ -154,15 +150,19 @@ import { computedMacroWithOptionalParams } from './util';
@return {Ember.computed} relationship
*/
function hasMany(type, options) {
if (typeof type === 'object') {
options = type;
type = undefined;
}

assert(
`The first argument to hasMany must be a string representing a model type key, not an instance of ${inspect(
type
)}. E.g., to define a relation to the Comment model, use hasMany('comment')`,
typeof type !== 'string'
typeof type === 'string' || typeof type === 'undefined'
);

options = options || {};
type = singularize(normalizeModelName(type));

// Metadata about relationships is stored on the meta of
// the relationship. This is used for introspection and
Expand Down
29 changes: 15 additions & 14 deletions packages/model/addon/-private/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ function findPossibleInverses(type, inverseType, name, relationshipsSoFar) {
return possibleRelationships;
}

/**
* This decorator allows us to lazily compute
* an expensive getter on first-access and therafter
* never recompute it.
*/
function computeOnce(target, key, desc) {
const cache = new WeakMap();
let getter = desc.get;
Expand Down Expand Up @@ -112,16 +117,8 @@ function computeOnce(target, key, desc) {
@uses EmberData.DeprecatedEvented
*/
class Model extends EmberObject {
init() {
super.init(...arguments);

if (DEBUG) {
if (!this._internalModel) {
throw new EmberError(
'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
);
}
}
constructor(args) {
super(args);

if (RECORD_DATA_ERRORS) {
this._invalidRequests = [];
Expand Down Expand Up @@ -2101,9 +2098,6 @@ class Model extends EmberObject {
return `model:${get(this, 'modelName')}`;
}
}
Model.prototype._internalModel = null;
Model.prototype.currentState = null;
Model.prototype.store = null;

const ID_DESCRIPTOR = {
configurable: false,
Expand All @@ -2124,7 +2118,8 @@ const ID_DESCRIPTOR = {
return;
}
}
get(this._internalModel, '_tag');
// consume the tracked tag
this._internalModel._tag;
return this._internalModel.id;
},
};
Expand Down Expand Up @@ -2258,6 +2253,12 @@ if (DEBUG) {
init() {
this._super(...arguments);

if (!this._internalModel) {
throw new EmberError(
'You should not call `create` on a model. Instead, call `store.createRecord` with the attributes you would like to set.'
);
}

if (DEPRECATE_EVENTED_API_USAGE) {
this._getDeprecatedEventedInfo = () => `${this._internalModel.modelName}#${this.id}`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type CoreStore = import('@ember-data/store/-private/system/core-store').default;
*/

function typeForRelationshipMeta(meta) {
let modelName = normalizeModelName(meta.type);
let modelName = normalizeModelName(meta.type || meta.key);

if (meta.kind === 'hasMany') {
modelName = singularize(modelName);
Expand Down
28 changes: 24 additions & 4 deletions packages/store/addon/-private/system/model/internal-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ function extractPivotName(name) {
*/
export default class InternalModel {
declare _id: string | null;
declare _tag: number;
declare modelName: string;
declare clientId: string;
declare __recordData: RecordData | null;
Expand Down Expand Up @@ -174,7 +173,6 @@ export default class InternalModel {
_getModelPackage();
}
this._id = identifier.id;
this._tag = 0;
this._isUpdatingId = false;
this.modelName = identifier.type;
this.clientId = identifier.lid;
Expand Down Expand Up @@ -220,6 +218,13 @@ export default class InternalModel {
}

@tracked currentState: any = RootState.empty;
/*
A tag which when dirtied allows things tracking a record's ID
to recompute. When we update this we must also flushSyncObservers
for pre-4.0 compat so we still call notifyPropertyChange('id')
on the record
*/
@tracked _tag: string = '';

get id(): string | null {
return this.identifier.id;
Expand All @@ -229,7 +234,7 @@ export default class InternalModel {
if (value !== this._id) {
let newIdentifier = { type: this.identifier.type, lid: this.identifier.lid, id: value };
identifierCacheFor(this.store).updateRecordIdentifier(this.identifier, newIdentifier);
set(this, '_tag', this._tag + 1);
this._tag = ''; // dirty tag
// TODO Show deprecation for private api
}
}
Expand Down Expand Up @@ -1258,6 +1263,21 @@ export default class InternalModel {
return { type: internalModel.modelName, id: internalModel.id };
}

/**
* calling `store.setRecordId` is necessary to update
* the cache index for this record if we have changed.
*
* However, since the store is not aware of whether the update
* is from us (via user set) or from a push of new data
* it will also call us so that we can notify and update state.
*
* When it does so it calls with `fromCache` so that we can
* short-circuit instead of cycling back.
*
* This differs from the short-circuit in the `_isUpdatingId`
* case in that the the cache can originate the call to setId,
* so on first entry we will still need to do our own update.
*/
setId(id: string, fromCache: boolean = false) {
if (this._isUpdatingId === true) {
return;
Expand All @@ -1278,7 +1298,7 @@ export default class InternalModel {
}

if (didChange && this.hasRecord) {
set(this, '_tag', this._tag + 1);
this._tag = ''; // dirty tag
if (CUSTOM_MODEL_CLASS) {
this.store._notificationManager.notify(this.identifier, 'identity');
} else {
Expand Down

0 comments on commit 4700c60

Please sign in to comment.