Skip to content

Commit

Permalink
Fix saving model metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
safo6m committed Oct 24, 2017
1 parent 7980fa0 commit cbf26d7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/constants/symbols.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// tslint:disable-next-line:variable-name
export const AttributeMetadata = Symbol('AttributeMetadata');
32 changes: 25 additions & 7 deletions src/decorators/attribute.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { format, parse } from 'date-fns';
import { AttributeMetadata } from '../constants/symbols';

export function Attribute(serializedName?: string) {
return function (target: any, propertyName: string) {
Expand All @@ -16,26 +17,43 @@ export function Attribute(serializedName?: string) {
return value;
};

const saveAnnotations = function (hasDirtyAttributes: boolean, oldValue: any, newValue: any, isNew: boolean) {
const annotations = Reflect.getMetadata('Attribute', target) || {};
const saveAnnotations = function () {
const metadata = Reflect.getMetadata('Attribute', target) || {};

metadata[propertyName] = {
marked: true
};

Reflect.defineMetadata('Attribute', metadata, target);
};

const setMetadata = function (
hasDirtyAttributes: boolean,
instance: any,
oldValue: any,
newValue: any,
isNew: boolean
) {
const targetType = Reflect.getMetadata('design:type', target, propertyName);

if (!instance[AttributeMetadata]) {
instance[AttributeMetadata] = {};
}

const mappingMetadata = Reflect.getMetadata('AttributeMapping', target) || {};
const serializedPropertyName = serializedName !== undefined ? serializedName : propertyName;
mappingMetadata[serializedPropertyName] = propertyName;
Reflect.defineMetadata('AttributeMapping', mappingMetadata, target);

const propertyHasDirtyAttributes = typeof oldValue === 'undefined' && !isNew ? false : hasDirtyAttributes;

annotations[propertyName] = {
instance[AttributeMetadata][propertyName] = {
newValue,
oldValue,
serializedName,
hasDirtyAttributes: propertyHasDirtyAttributes,
serialisationValue: converter(targetType, newValue, true)
};

Reflect.defineMetadata('Attribute', annotations, target);
};

const getter = function () {
Expand All @@ -47,13 +65,13 @@ export function Attribute(serializedName?: string) {
const convertedValue = converter(targetType, newVal);

if (convertedValue !== this['_' + propertyName]) {
saveAnnotations(true, this['_' + propertyName], newVal, !this.id);
setMetadata(true, this, this['_' + propertyName], newVal, !this.id);
this['_' + propertyName] = convertedValue;
}
};

if (delete target[propertyName]) {
saveAnnotations(false, undefined, target[propertyName], target.id);
saveAnnotations();
Object.defineProperty(target, propertyName, {
get: getter,
set: setter,
Expand Down
10 changes: 6 additions & 4 deletions src/models/json-api.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Observable } from 'rxjs/Observable';
import { JsonApiDatastore, ModelType } from '../services/json-api-datastore.service';
import { ModelConfig } from '../interfaces/model-config.interface';
import * as _ from 'lodash';
import { AttributeMetadata } from '../constants/symbols';

export class JsonApiModel {
id: string;
Expand All @@ -26,12 +27,12 @@ export class JsonApiModel {
}

save(params?: any, headers?: Headers): Observable<this> {
const attributesMetadata: any = Reflect.getMetadata('Attribute', this);
const attributesMetadata: any = this[AttributeMetadata];
return this._datastore.saveRecord(attributesMetadata, this, params, headers);
}

get hasDirtyAttributes() {
const attributesMetadata: any = Reflect.getMetadata('Attribute', this);
const attributesMetadata: any = this[AttributeMetadata];
let hasDirtyAttributes = false;
for (const propertyName in attributesMetadata) {
if (attributesMetadata.hasOwnProperty(propertyName)) {
Expand All @@ -47,7 +48,7 @@ export class JsonApiModel {
}

rollbackAttributes(): void {
const attributesMetadata: any = Reflect.getMetadata('Attribute', this);
const attributesMetadata: any = this[AttributeMetadata];
let metadata: any;
for (const propertyName in attributesMetadata) {
if (attributesMetadata.hasOwnProperty(propertyName)) {
Expand All @@ -62,7 +63,8 @@ export class JsonApiModel {
}
}
}
Reflect.defineMetadata('Attribute', attributesMetadata, this);

this[AttributeMetadata] = attributesMetadata;
}

get modelConfig(): ModelConfig {
Expand Down
5 changes: 3 additions & 2 deletions src/services/json-api-datastore.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { JsonApiQueryData } from '../models/json-api-query-data';
import * as qs from 'qs';
import { DatastoreConfig } from '../interfaces/datastore-config.interface';
import { ModelConfig } from '../interfaces/model-config.interface';
import { AttributeMetadata } from '../constants/symbols';

export type ModelType<T extends JsonApiModel> = { new(datastore: JsonApiDatastore, data: any): T; };

Expand Down Expand Up @@ -359,7 +360,7 @@ export class JsonApiDatastore {
private resetMetadataAttributes<T extends JsonApiModel>(res: T, attributesMetadata: any, modelType: ModelType<T>) {
// TODO check why is attributesMetadata from the arguments never used
// tslint:disable-next-line:no-param-reassign
attributesMetadata = Reflect.getMetadata('Attribute', res);
attributesMetadata = res[AttributeMetadata];

for (const propertyName in attributesMetadata) {
if (attributesMetadata.hasOwnProperty(propertyName)) {
Expand All @@ -371,7 +372,7 @@ export class JsonApiDatastore {
}
}

Reflect.defineMetadata('Attribute', attributesMetadata, res);
res[AttributeMetadata] = attributesMetadata;
return res;
}

Expand Down

0 comments on commit cbf26d7

Please sign in to comment.