Skip to content

Commit

Permalink
Implemented exists capability across all models in the constructor, f…
Browse files Browse the repository at this point in the history
…ixed tests that were broken by the feature
  • Loading branch information
zakhenry committed Aug 28, 2015
1 parent d7e55e4 commit f5cf76f
Show file tree
Hide file tree
Showing 15 changed files with 69 additions and 61 deletions.
2 changes: 1 addition & 1 deletion app/src/app/admin/articles/article/article.ts
Expand Up @@ -92,7 +92,7 @@ namespace app.admin.articles.article {
*/
public save(){

return this.articleService.saveArticleWithRelated(this.article, this.$stateParams.newArticle)
return this.articleService.saveArticleWithRelated(this.article)
.then(() => {
this.notificationService.toast('Article saved').pop();
});
Expand Down
6 changes: 3 additions & 3 deletions app/src/common/models/abstractModel.spec.ts
Expand Up @@ -13,9 +13,9 @@ namespace common.models {
public _hasOne:TestChildModel;
public _hasMany:TestChildModel[];

constructor(data:any) {
super(data);
this.hydrate(data);
constructor(data:any, exists:boolean = false) {
super(data, exists);
this.hydrate(data, exists);
}

}
Expand Down
29 changes: 17 additions & 12 deletions app/src/common/models/abstractModel.ts
Expand Up @@ -6,34 +6,35 @@ namespace common.models {
}

export interface IModelFactory{
(data:any):IModel;
(data:any, exists?:boolean):IModel;
}

export class AbstractModel implements IModel {

protected _nestedEntityMap;
private _exists:boolean;

constructor(data?:any) {
this.hydrate(data);
constructor(data?:any, exists:boolean = false) {
this.hydrate(data, exists);

Object.defineProperty(this, "_exists", {
enumerable: false,
writable: true,
value: false,
value: exists,
});
}

/**
* Assign the properties of the model from the init data
* @param data
* @param exists
*/
protected hydrate(data?:any) {
protected hydrate(data:any, exists:boolean) {
if (_.isObject(data)) {
_.assign(this, data);

if (_.size(this._nestedEntityMap) > 1) {
this.hydrateNested(data);
this.hydrateNested(data, exists);
}
}

Expand All @@ -42,18 +43,19 @@ namespace common.models {
/**
* Find all the nested entities and hydrate them into model instances
* @param data
* @param exists
*/
protected hydrateNested(data:any){
protected hydrateNested(data:any, exists:boolean){

_.forIn(this._nestedEntityMap, (model:typeof AbstractModel, nestedKey:string) => {

let key = '_' + nestedKey;
if (_.has(data, key) && !_.isNull(data[key])){

if (_.isArray(data[key])){
this[key] = _.map(data[key], (entityData) => this.hydrateModel(entityData, model));
this[key] = _.map(data[key], (entityData) => this.hydrateModel(entityData, model, exists));
}else if (_.isObject(data[key])){
this[key] = this.hydrateModel(data[key], model);
this[key] = this.hydrateModel(data[key], model, exists);
}

}else{
Expand All @@ -68,12 +70,15 @@ namespace common.models {
* Get a new instance of a model from data
* @param data
* @param Model
* @returns {undefined}
* @returns {common.models.AbstractModel}
* @param exists
*/
private hydrateModel(data:any, Model:typeof AbstractModel){
private hydrateModel(data:any, Model:typeof AbstractModel, exists:boolean){

return new Model(data);
let model = new Model(data);
model.setExists(exists);

return model;
}

/**
Expand Down
6 changes: 3 additions & 3 deletions app/src/common/models/article/articleModel.ts
Expand Up @@ -16,9 +16,9 @@ namespace common.models {

public _tags:common.models.Tag[];

constructor(data:any) {
super(data);
this.hydrate(data);
constructor(data:any, exists:boolean = false) {
super(data, exists);
this.hydrate(data, exists);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions app/src/common/models/tag/tagModel.ts
Expand Up @@ -6,9 +6,9 @@ namespace common.models {
public tagId:string = undefined;
public tag:string = undefined;

constructor(data:any) {
super(data);
this.hydrate(data);
constructor(data:any, exists:boolean = false) {
super(data, exists);
this.hydrate(data, exists);
}

}
Expand Down
6 changes: 3 additions & 3 deletions app/src/common/models/user/userModel.ts
Expand Up @@ -20,9 +20,9 @@ namespace common.models {
public _socialLogins:common.models.UserSocialLogin[] = undefined;
public userType:string = undefined;

constructor(data:any) {
super(data);
this.hydrate(data);
constructor(data:any, exists:boolean = false) {
super(data, exists);
this.hydrate(data, exists);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions app/src/common/models/user/userProfileModel.ts
Expand Up @@ -23,9 +23,9 @@ module common.models {
{label: 'Prefer not to say', value: 'N/A'}
];

constructor(data:any) {
super(data);
this.hydrate(data);
constructor(data:any, exists:boolean = false) {
super(data, exists);
this.hydrate(data, exists);
}

}
Expand Down
6 changes: 3 additions & 3 deletions app/src/common/models/user/userSocialLoginModel.ts
Expand Up @@ -10,9 +10,9 @@ module common.models {
public provider:string = undefined;
public token:string = undefined;

constructor(data:any) {
super(data);
this.hydrate(data);
constructor(data:any, exists:boolean = false) {
super(data, exists);
this.hydrate(data, exists);
}

}
Expand Down
2 changes: 1 addition & 1 deletion app/src/common/services/article/articleService.spec.ts
Expand Up @@ -141,7 +141,7 @@
$httpBackend.expectPUT('/api/articles/'+article.articleId, article.getAttributes()).respond(201);
$httpBackend.expectPUT('/api/articles/'+article.articleId+'/tags', _.clone(article._tags, true)).respond(201);

let savePromise = articleService.saveArticleWithRelated(article, true);
let savePromise = articleService.saveArticleWithRelated(article);

expect(savePromise).eventually.to.be.fulfilled;
expect(savePromise).eventually.to.deep.equal(article);
Expand Down
30 changes: 14 additions & 16 deletions app/src/common/services/article/articleService.ts
Expand Up @@ -15,9 +15,10 @@ namespace common.services.article {
* Get an instance of the Article given data
* @param data
* @returns {common.models.Article}
* @param exists
*/
public static articleFactory(data:any):common.models.Article {
return new common.models.Article(data);
public static articleFactory(data:any, exists:boolean = false):common.models.Article {
return new common.models.Article(data, exists);
}

/**
Expand Down Expand Up @@ -65,16 +66,15 @@ namespace common.services.article {
/**
* Save the article with all the nested entities too
* @param article
* @param newArticle
* @returns {IPromise<common.models.Article>}
*/
public saveArticleWithRelated(article:common.models.Article, newArticle:boolean = false):ng.IPromise<common.models.Article>{
public saveArticleWithRelated(article:common.models.Article):ng.IPromise<common.models.Article>{


return this.saveArticle(article, newArticle)
.then(() => this.saveRelatedEntities(article, newArticle))
return this.saveArticle(article)
.then(() => this.saveRelatedEntities(article))
.then(() => {
(<common.decorators.IChangeAwareDecorator>article).resetChangedProperties(); //reset so next save only saves the changed ones
article.setExists(true);
return article;
})
;
Expand All @@ -84,16 +84,15 @@ namespace common.services.article {
/**
* Save the article
* @param article
* @param newArticle
* @returns ng.IPromise<common.models.Article>
*/
public saveArticle(article:common.models.Article, newArticle:boolean = false):ng.IPromise<common.models.Article|boolean>{
public saveArticle(article:common.models.Article):ng.IPromise<common.models.Article|boolean>{

let method = newArticle ? 'put' : 'patch';
let method = article.exists() ? 'patch' : 'put';

let saveData = article.getAttributes();

if (!newArticle) {
if (article.exists()) {
saveData = (<common.decorators.IChangeAwareDecorator>article).getChanged();
}

Expand All @@ -111,10 +110,10 @@ namespace common.services.article {
* @param article
* @returns {IPromise<any[]>}
*/
private saveRelatedEntities(article:common.models.Article, newArticle:boolean = false):ng.IPromise<any> {
private saveRelatedEntities(article:common.models.Article):ng.IPromise<any> {

return this.$q.all([ //save all related entities
this.saveArticleTags(article, newArticle),
this.saveArticleTags(article),
]);

}
Expand All @@ -124,11 +123,11 @@ namespace common.services.article {
* @param article
* @returns {any}
*/
private saveArticleTags(article:common.models.Article, newArticle:boolean = false):ng.IPromise<common.models.Tag[]|boolean>{
private saveArticleTags(article:common.models.Article):ng.IPromise<common.models.Tag[]|boolean>{

let tagData = _.clone(article._tags);

if (!newArticle){
if (article.exists()){

let changes:any = (<common.decorators.IChangeAwareDecorator>article).getChanged(true);
if (!_.has(changes, '_tags')){
Expand All @@ -138,7 +137,6 @@ namespace common.services.article {

return this.ngRestAdapter.put('/articles/'+article.articleId+'/tags', tagData)
.then(() => {
console.log('tags saved');
return article._tags;
});

Expand Down
2 changes: 1 addition & 1 deletion app/src/common/services/auth/authService.ts
Expand Up @@ -40,7 +40,7 @@ namespace common.services.auth {

return this.ngJwtAuthService
.registerUserFactory((subClaim: string, tokenData: global.JwtAuthClaims): ng.IPromise<common.models.User> => {
return this.$q.when(new common.models.User(tokenData._user));
return this.$q.when(new common.models.User(tokenData._user, true));
})
.registerLoginPromptFactory((deferredCredentials:ng.IDeferred<NgJwtAuth.ICredentials>, loginSuccessPromise:ng.IPromise<NgJwtAuth.IUser>, currentUser:NgJwtAuth.IUser): ng.IPromise<any> => {

Expand Down
4 changes: 2 additions & 2 deletions app/src/common/services/pagination/paginationService.ts
Expand Up @@ -27,7 +27,7 @@ namespace common.services.pagination {
private $q:ng.IQService,
private $window:ng.IWindowService) {

this.modelFactory = (data:any) => data; //set a default factory that just returns the data
this.modelFactory = (data:any, exists:boolean) => data; //set a default factory that just returns the data

}

Expand Down Expand Up @@ -83,7 +83,7 @@ namespace common.services.pagination {
Range: Paginator.getRangeHeader(index, last)
}).then((response:ng.IHttpPromiseCallbackArg<any>) => {
this.processContentRangeHeader(response.headers);
return _.map(response.data, (modelData) => this.modelFactory(modelData));
return _.map(response.data, (modelData) => this.modelFactory(modelData, true));
}).catch((response:ng.IHttpPromiseCallbackArg<any>) => {
if(response.status == 404){ //no content
this.entityCountTotal = 0;
Expand Down
5 changes: 3 additions & 2 deletions app/src/common/services/tag/tagService.ts
Expand Up @@ -16,9 +16,10 @@ namespace common.services.tag {
* Get an instance of the Tag given data
* @param data
* @returns {common.models.Tag}
* @param exists
*/
public static tagFactory(data:any):common.models.Tag {
return new common.models.Tag(data);
public static tagFactory(data:any, exists:boolean = false):common.models.Tag {
return new common.models.Tag(data, exists);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion app/src/common/services/user/userService.spec.ts
Expand Up @@ -290,7 +290,7 @@

it('should be able to send a patch request to update the user details (including profile)', () => {

let user = _.clone(fixtures.user);
let user = fixtures.user;

let profile = _.clone(userProfile);

Expand Down
18 changes: 11 additions & 7 deletions app/src/common/services/user/userService.ts
Expand Up @@ -20,10 +20,11 @@ namespace common.services.user {
/**
* Get an instance of a user from data
* @param userData
* @returns {common.services.user.User}
* @returns {common.models.User}
* @param exists
*/
public static userFactory(userData:global.IUserData):common.models.User {
return new common.models.User(userData);
public static userFactory(userData:global.IUserData, exists:boolean = false):common.models.User {
return new common.models.User(userData, exists);
}

/**
Expand Down Expand Up @@ -66,7 +67,10 @@ namespace common.services.user {
let user = new common.models.User(userData);

return this.ngRestAdapter.put('/users/' + user.userId, user)
.then(() => user); //return this user object
.then(() => {
user.setExists(true);
return user;
}); //return this user object
}

/**
Expand Down Expand Up @@ -148,20 +152,20 @@ namespace common.services.user {
*/
public updateUser(user:common.models.User):ng.IPromise<any> {
return this.ngRestAdapter
.patch('/users/' + user.userId, user);
.patch('/users/' + user.userId, user.getAttributes(true));
}

/**
* Get full user information
* @param user
* @returns {ng.IHttpPromise<any>}
* @returns {ng.IPromise<common.models.User>}
*/
public getUser(user:common.models.User):ng.IPromise<common.models.User> {
return this.ngRestAdapter.get('/users/' + user.userId, {
'With-Nested' : 'userCredential, userProfile, socialLogins'
})
.then((res) => {
return new common.models.User(res.data);
return new common.models.User(res.data, true);
});
}

Expand Down

0 comments on commit f5cf76f

Please sign in to comment.