From f3e48264f14aa3a435c256aa12fcf26c5319d7e9 Mon Sep 17 00:00:00 2001 From: RobinBuschmann Date: Sat, 15 Jul 2017 20:17:59 +0200 Subject: [PATCH 1/2] fixes 37 --- lib/models/v3/Model.ts | 18 +++++++++++++- lib/models/v3/Sequelize.ts | 2 +- test/models/ShoeWithScopes.ts | 8 ++++++ test/specs/scopes.spec.ts | 46 +++++++++++++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/lib/models/v3/Model.ts b/lib/models/v3/Model.ts index a5d67e57..65b3d391 100644 --- a/lib/models/v3/Model.ts +++ b/lib/models/v3/Model.ts @@ -34,10 +34,26 @@ export const Model: any = (() => { if (typeof SeqModelProto[key] === 'function') { _Model[key] = function(...args: any[]): any { - return SeqModelProto[key].call(this.Model || this, ...args); + + let targetModel = this.Model; + + if (this.scoped) { + // Adds scope info to 'this' context + targetModel = Object.create(targetModel); + targetModel.$scope = this.$scope; + targetModel.scoped = this.scoped; + } + + return SeqModelProto[key].call(targetModel, ...args); }; } }); + // 'scope' need to be called with 'this'context + // instead of 'this.Model' context + _Model['scope'] = function(...args: any[]): any { + return SeqModelProto.scope.call(this, ...args); + }; + return _Model; })(); diff --git a/lib/models/v3/Sequelize.ts b/lib/models/v3/Sequelize.ts index 24cf6d0b..331f58f2 100644 --- a/lib/models/v3/Sequelize.ts +++ b/lib/models/v3/Sequelize.ts @@ -103,7 +103,7 @@ export class Sequelize extends SequelizeOrigin implements BaseSequelize { // this initializes some stuff for Instance model['refreshAttributes'](); - // copy static fields to class + // copy own static fields to class Object.keys(model).forEach(key => key !== 'name' && (_class[key] = model[key])); // the class needs to know its sequelize model diff --git a/test/models/ShoeWithScopes.ts b/test/models/ShoeWithScopes.ts index 73e7d102..57d25980 100644 --- a/test/models/ShoeWithScopes.ts +++ b/test/models/ShoeWithScopes.ts @@ -1,6 +1,7 @@ import {Table, Model, Column, ForeignKey, BelongsTo, DefaultScope, Scopes} from "../../index"; import {Manufacturer} from "./Manufacturer"; +import {Person} from "./Person"; export const SHOE_DEFAULT_SCOPE = { attributes: ['id', 'primaryColor', 'secondaryColor', 'producedAt'] @@ -41,4 +42,11 @@ export class ShoeWithScopes extends Model { @BelongsTo(() => Manufacturer) manufacturer: Manufacturer; + @ForeignKey(() => Person) + @Column + ownerId: number; + + @BelongsTo(() => Person) + owner: Person; + } diff --git a/test/specs/scopes.spec.ts b/test/specs/scopes.spec.ts index 3bd12b39..bea986cd 100644 --- a/test/specs/scopes.spec.ts +++ b/test/specs/scopes.spec.ts @@ -1,8 +1,12 @@ -import {expect} from 'chai'; +import {expect, use} from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; import {createSequelize} from "../utils/sequelize"; import {getScopeOptions} from "../../lib/services/models"; import {ShoeWithScopes, SHOE_DEFAULT_SCOPE, SHOE_SCOPES} from "../models/ShoeWithScopes"; import {Manufacturer} from "../models/Manufacturer"; +import {Person} from "../models/Person"; + +use(chaiAsPromised); describe('scopes', () => { @@ -28,6 +32,7 @@ describe('scopes', () => { describe('find', () => { const BRAND = 'adiwas'; + const OWNER = 'bob'; beforeEach(() => ShoeWithScopes .create({ @@ -37,8 +42,11 @@ describe('scopes', () => { producedAt: new Date(), manufacturer: { brand: BRAND + }, + owner: { + name: OWNER } - }, {include: [Manufacturer]})); + }, {include: [Manufacturer, Person]})); it('should consider default scope', () => @@ -64,6 +72,40 @@ describe('scopes', () => { }) ); + describe('with include options', () => { + + it('should consider scopes and additional included model (object)', () => + expect(ShoeWithScopes + .scope('full') + .findOne({ + include: [{ + model: Person, + }] + }) + .then(shoe => { + expect(shoe).to.have.property('manufacturer').which.is.not.null; + expect(shoe).to.have.property('manufacturer').which.have.property('brand', BRAND); + expect(shoe).to.have.property('owner').which.is.not.null; + }) + ).not.to.be.rejected + ); + + it('should consider scopes and additional included model (model)', () => + expect(ShoeWithScopes + .scope('full') + .findOne({ + include: [Person] + }) + .then(shoe => { + expect(shoe).to.have.property('manufacturer').which.is.not.null; + expect(shoe).to.have.property('manufacturer').which.have.property('brand', BRAND); + expect(shoe).to.have.property('owner').which.is.not.null; + }) + ).not.to.be.rejected + ); + + }); + }); }); From 90c419c0a75ddabe9d583bd96c69c9ec338ea602 Mon Sep 17 00:00:00 2001 From: RobinBuschmann Date: Sun, 16 Jul 2017 14:24:23 +0200 Subject: [PATCH 2/2] fixes same issue for unscoped --- lib/models/v3/Model.ts | 6 +++--- test/specs/scopes.spec.ts | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/models/v3/Model.ts b/lib/models/v3/Model.ts index 65b3d391..eb2b4b2d 100644 --- a/lib/models/v3/Model.ts +++ b/lib/models/v3/Model.ts @@ -37,7 +37,7 @@ export const Model: any = (() => { let targetModel = this.Model; - if (this.scoped) { + if (this.scoped !== undefined) { // Adds scope info to 'this' context targetModel = Object.create(targetModel); targetModel.$scope = this.$scope; @@ -49,9 +49,9 @@ export const Model: any = (() => { } }); - // 'scope' need to be called with 'this'context + // 'scope' and 'unscoped' need to be called with 'this' context // instead of 'this.Model' context - _Model['scope'] = function(...args: any[]): any { + _Model['scope'] = _Model['unscoped'] = function(...args: any[]): any { return SeqModelProto.scope.call(this, ...args); }; diff --git a/test/specs/scopes.spec.ts b/test/specs/scopes.spec.ts index bea986cd..79df58bc 100644 --- a/test/specs/scopes.spec.ts +++ b/test/specs/scopes.spec.ts @@ -72,6 +72,16 @@ describe('scopes', () => { }) ); + it('should not consider default scope due to unscoped call', () => + + ShoeWithScopes + .unscoped() + .findOne() + .then(shoe => { + expect(shoe).to.have.property('secretKey').which.is.not.null; + }) + ); + describe('with include options', () => { it('should consider scopes and additional included model (object)', () => @@ -104,6 +114,32 @@ describe('scopes', () => { ).not.to.be.rejected ); + it('should not consider default scope due to unscoped call, but additonal includes (object)', () => + + ShoeWithScopes + .unscoped() + .findOne({ + include: [{model: Person}] + }) + .then(shoe => { + expect(shoe).to.have.property('secretKey').which.is.not.null; + expect(shoe).to.have.property('owner').which.is.not.null; + }) + ); + + it('should not consider default scope due to unscoped call, but additonal includes (model)', () => + + ShoeWithScopes + .unscoped() + .findOne({ + include: [Person] + }) + .then(shoe => { + expect(shoe).to.have.property('secretKey').which.is.not.null; + expect(shoe).to.have.property('owner').which.is.not.null; + }) + ); + }); });