diff --git a/es5/lib/model/delete.js b/es5/lib/model/delete.js index ffdeb57..4a14054 100644 --- a/es5/lib/model/delete.js +++ b/es5/lib/model/delete.js @@ -39,7 +39,7 @@ var _jargon2 = _interopRequireDefault(_jargon); function deleteSelf(callback) { var _this = this; - if (!this.constructor.database) { + if (!this[_symbols2["default"].getDatabase]()) { throw new Error("Cannot delete without Model.database set."); } @@ -80,7 +80,7 @@ function softDelete(callback) { var now = new _fleming2["default"](); var attributesToUpdate = {}; attributesToUpdate[(0, _jargon2["default"])("deletedAt").snake.toString()] = now.toDate(); - _this2.constructor.database.update(attributesToUpdate).into(_this2.tableName).where(_this2.primaryKey, "=", _this2[_this2.primaryKey]).results(function (error, results) { + _this2[_symbols2["default"].getDatabase]().update(attributesToUpdate).into(_this2.tableName).where(_this2.primaryKey, "=", _this2[_this2.primaryKey]).results(function (error, results) { if (error) { next(error); } else if (results === 0) { diff --git a/es5/lib/model/fetch.js b/es5/lib/model/fetch.js index fb09aaa..e55cd90 100644 --- a/es5/lib/model/fetch.js +++ b/es5/lib/model/fetch.js @@ -39,7 +39,7 @@ var fetchByAssociations = { function fetchByHasOne(associationName, associations, callback) { var _this = this; - var modelFinder = new _modelFinderJs2["default"](this.constructor.database); + var modelFinder = new _modelFinderJs2["default"](this[_symbols2["default"].getDatabase]()); var association = associations[associationName]; var ModelClass = association.constructor; @@ -99,7 +99,7 @@ function fetchByHasOne(associationName, associations, callback) { } function fetchWhere(modelClass, key, conditionType, ids, target, callback) { - var modelFinder = new _modelFinderJs2["default"](this.constructor.database); + var modelFinder = new _modelFinderJs2["default"](this[_symbols2["default"].getDatabase]()); modelFinder.find(modelClass).where(key, conditionType, ids).results(function (findErrors, resultModels) { resultModels.forEach(function (model) { target.push(model); @@ -111,14 +111,13 @@ function fetchWhere(modelClass, key, conditionType, ids, target, callback) { function fetchByHasMany(associationName, associations, callback) { var _this3 = this; - var modelFinder = new _modelFinderJs2["default"](this.constructor.database); var association = associations[associationName]; if (association.through) { (function () { var throughAssociation = associations[association.through]; - modelFinder.find(throughAssociation.constructor).where(association.foreignId, _this3[_this3.primaryKey]).results(function (errors, models) { + throughAssociation.constructor.find.where(association.foreignId, _this3[_this3.primaryKey]).results(function (errors, models) { if (models.length > 0) { (function () { var foreignAssociationName = association.as || associationName; @@ -167,7 +166,7 @@ function fetchByHasMany(associationName, associations, callback) { function fetchByBelongsTo(associationName, associations, callback) { var _this4 = this; - var modelFinder = new _modelFinderJs2["default"](this.constructor.database); + var modelFinder = new _modelFinderJs2["default"](this[_symbols2["default"].getDatabase]()); var association = associations[associationName]; if (!this[association.foreignId]) { @@ -188,11 +187,12 @@ function fetchBy() { var fields = arguments.length <= 0 || arguments[0] === undefined ? [this.primaryKey] : arguments[0]; var callback = arguments.length <= 1 || arguments[1] === undefined ? undefined : arguments[1]; - if (!this.constructor.database) { + var database = this[_symbols2["default"].getDatabase](); + if (!database) { throw new Error("Cannot fetch without Model.database set."); } - var chain = this.constructor.database.select("*").from(this.tableName); + var chain = database.select("*").from(this.tableName); fields.forEach(function (field, index) { if (!_this5[field]) { throw new Error("Cannot fetch this model by the '" + field + "' field because it is not set."); diff --git a/es5/lib/model/index.js b/es5/lib/model/index.js index 68be9fb..65a2e7d 100644 --- a/es5/lib/model/index.js +++ b/es5/lib/model/index.js @@ -54,7 +54,7 @@ var Model = (function () { * @constructor */ - function Model(initialAttributes) { + function Model(initialAttributes, options) { var _this = this; _classCallCheck(this, Model); @@ -67,6 +67,10 @@ var Model = (function () { _._primaryKey = null; _._softDelete = null; + if (options !== undefined) { + _._database = options.database; + } + /** * Define dynamic properties */ @@ -328,7 +332,15 @@ var Model = (function () { /** * Private Functionality */ - + }, { + key: _symbols2["default"].getDatabase, + value: function value() { + var database = (0, _incognito2["default"])(this)._database; + if (!database) { + database = this.constructor.database; + } + return database; + } }, { key: _symbols2["default"].setAttributes, value: function value(newAttributes) { @@ -487,9 +499,21 @@ Object.assign(Model.prototype, _defineProperty({ }, _symbols2["default"].addAssociation, require("./addAssociation.js"))); Object.defineProperties(Model, { + "database": { + get: function getDatabase() { + var database = this._database; + if (!database) { + database = Model._database; + } + return database; + }, + set: function setDatabase(value) { + this._database = value; + } + }, "find": { get: function modelFind() { - var modelQuery = new _modelFinderJs2["default"](Model.database); + var modelQuery = new _modelFinderJs2["default"](this.database); return modelQuery.find(this); } } diff --git a/es5/lib/model/save.js b/es5/lib/model/save.js index 8a3f66d..7b4fb20 100644 --- a/es5/lib/model/save.js +++ b/es5/lib/model/save.js @@ -19,6 +19,10 @@ var _fleming = require("fleming"); var _fleming2 = _interopRequireDefault(_fleming); +var _incognito = require("incognito"); + +var _incognito2 = _interopRequireDefault(_incognito); + var _symbols = require("./symbols"); var _symbols2 = _interopRequireDefault(_symbols); @@ -51,7 +55,7 @@ function saveOrUpdate(callback) { this.createdAt = now.toDate(); var fieldAttributes = this[_symbols2["default"].getFieldAttributes](); - this.constructor.database.insert(fieldAttributes).into(this.tableName).results(function (error, ids) { + this[_symbols2["default"].getDatabase]().insert(fieldAttributes).into(this.tableName).results(function (error, ids) { if (error) { callback(error); } else { @@ -70,7 +74,7 @@ function saveOrUpdate(callback) { } } - this.constructor.database.update(updateAttributes).into(this.tableName).where(this.primaryKey, "=", this[this.primaryKey]).results(callback); + this[_symbols2["default"].getDatabase]().update(updateAttributes).into(this.tableName).where(this.primaryKey, "=", this[this.primaryKey]).results(callback); } } @@ -110,7 +114,7 @@ function validate(callback) { function save(callback) { var _this3 = this; - if (!this.constructor.database) { + if (!this[_symbols2["default"].getDatabase]()) { throw new Error("Cannot save without Model.database set."); } diff --git a/es5/lib/model/symbols.js b/es5/lib/model/symbols.js index f89284f..e9db3a1 100644 --- a/es5/lib/model/symbols.js +++ b/es5/lib/model/symbols.js @@ -12,5 +12,6 @@ module.exports = { properties: Symbol(), validations: Symbol(), isNew: Symbol(), - fetchBy: Symbol() + fetchBy: Symbol(), + getDatabase: Symbol() }; \ No newline at end of file diff --git a/es5/spec/model.spec.js b/es5/spec/model.spec.js index c8f5ae9..ff8a830 100644 --- a/es5/spec/model.spec.js +++ b/es5/spec/model.spec.js @@ -335,6 +335,56 @@ describe("Model(attributes, options)", function () { users.length.should.equal(5); }); }); + + describe("(with a different database for a model)", function () { + var Car = (function (_Model2) { + _inherits(Car, _Model2); + + function Car() { + _classCallCheck(this, Car); + + _get(Object.getPrototypeOf(Car.prototype), "constructor", this).apply(this, arguments); + } + + return Car; + })(_2["default"]); + + var car = undefined, + database = undefined, + query = undefined; + + describe("(static way)", function () { + beforeEach(function () { + database = new _almaden2["default"](_databaseConfigJson2["default"]); + Car.database = database; + query = database.spy("select * from `cars`", []); + car = new Car(); + }); + + it("should use the specific model class database", function (done) { + Car.find.all.results(function () { + query.callCount.should.equal(1); + done(); + }); + }); + }); + + describe("(instance way)", function () { + beforeEach(function () { + database = new _almaden2["default"](_databaseConfigJson2["default"]); + Car.database = null; + car = new Car({ id: 2 }, { database: database }); + query = database.spy("select * from `cars` where `id` = 2 limit 1", []); + }); + + it("should use the specific model instance database", function (done) { + car.fetch(function () { + query.callCount.should.equal(1); + done(); + }); + }); + }); + }); }); }); @@ -347,8 +397,8 @@ describe("Model(attributes, options)", function () { validateSpy = undefined, associateSpy = undefined; - var Post = (function (_Model2) { - _inherits(Post, _Model2); + var Post = (function (_Model3) { + _inherits(Post, _Model3); function Post() { _classCallCheck(this, Post); @@ -412,8 +462,8 @@ describe("Model(attributes, options)", function () { }); describe("(Associations)", function () { - var Street = (function (_Model3) { - _inherits(Street, _Model3); + var Street = (function (_Model4) { + _inherits(Street, _Model4); function Street() { _classCallCheck(this, Street); @@ -424,8 +474,8 @@ describe("Model(attributes, options)", function () { return Street; })(_2["default"]); - var Driver = (function (_Model4) { - _inherits(Driver, _Model4); + var Driver = (function (_Model5) { + _inherits(Driver, _Model5); function Driver() { _classCallCheck(this, Driver); @@ -436,8 +486,8 @@ describe("Model(attributes, options)", function () { return Driver; })(_2["default"]); - var Truck = (function (_Model5) { - _inherits(Truck, _Model5); + var Truck = (function (_Model6) { + _inherits(Truck, _Model6); function Truck() { _classCallCheck(this, Truck); @@ -448,8 +498,8 @@ describe("Model(attributes, options)", function () { return Truck; })(_2["default"]); - var Wheel = (function (_Model6) { - _inherits(Wheel, _Model6); + var Wheel = (function (_Model7) { + _inherits(Wheel, _Model7); function Wheel() { _classCallCheck(this, Wheel); @@ -460,8 +510,8 @@ describe("Model(attributes, options)", function () { return Wheel; })(_2["default"]); - var SteeringWheel = (function (_Model7) { - _inherits(SteeringWheel, _Model7); + var SteeringWheel = (function (_Model8) { + _inherits(SteeringWheel, _Model8); function SteeringWheel() { _classCallCheck(this, SteeringWheel); diff --git a/es5/spec/model/delete.spec.js b/es5/spec/model/delete.spec.js index 960565b..cc62ddf 100644 --- a/es5/spec/model/delete.spec.js +++ b/es5/spec/model/delete.spec.js @@ -263,7 +263,7 @@ describe("Model(attributes, options)", function () { describe("(Model.database not set)", function () { beforeEach(function () { - delete _2["default"].database; + delete _2["default"]._database; }); it("should throw an error", function () { diff --git a/es5/spec/model/destroy.spec.js b/es5/spec/model/destroy.spec.js index 8d745b1..b07671b 100644 --- a/es5/spec/model/destroy.spec.js +++ b/es5/spec/model/destroy.spec.js @@ -194,7 +194,7 @@ // // describe("(Model.database not set)", () => { // beforeEach(() => { -// delete Model.database; +// delete Model._database; // }); // // it("should throw an error", () => { diff --git a/es5/spec/model/fetch.spec.js b/es5/spec/model/fetch.spec.js index 9f83f47..19c8c3c 100644 --- a/es5/spec/model/fetch.spec.js +++ b/es5/spec/model/fetch.spec.js @@ -155,7 +155,7 @@ describe(".fetch(callback)", function () { describe("(Model.database not set)", function () { beforeEach(function () { - delete _2["default"].database; + delete _2["default"]._database; }); it("should throw an error", function () { @@ -228,7 +228,7 @@ describe(".fetch(callback)", function () { describe("(Model.database not set)", function () { beforeEach(function () { - delete _2["default"].database; + delete _2["default"]._database; }); it("should throw an error", function () { @@ -305,7 +305,7 @@ describe(".fetch(callback)", function () { describe("(Model.database not set)", function () { beforeEach(function () { - delete _2["default"].database; + delete _2["default"]._database; }); it("should throw an error", function () { diff --git a/es5/spec/model/save.spec.js b/es5/spec/model/save.spec.js index bbb1af1..50e9df6 100644 --- a/es5/spec/model/save.spec.js +++ b/es5/spec/model/save.spec.js @@ -355,7 +355,7 @@ describe("Model(attributes, options)", function () { describe("(Model.database is NOT set)", function () { beforeEach(function () { - delete _2["default"].database; + delete _2["default"]._database; }); it("should call back with an error", function () { diff --git a/es6/lib/model/delete.js b/es6/lib/model/delete.js index 7690459..056a91c 100644 --- a/es6/lib/model/delete.js +++ b/es6/lib/model/delete.js @@ -13,7 +13,7 @@ import inflect from "jargon"; * @param {Function} callback */ export default function deleteSelf(callback) { - if (!this.constructor.database) { throw new Error("Cannot delete without Model.database set."); } + if (!this[symbols.getDatabase]()) { throw new Error("Cannot delete without Model.database set."); } flowsync.series([ (done) => { @@ -57,7 +57,7 @@ function softDelete(callback) { let now = new Datetime(); let attributesToUpdate = {}; attributesToUpdate[inflect("deletedAt").snake.toString()] = now.toDate(); - this.constructor.database + this[symbols.getDatabase]() .update(attributesToUpdate) .into(this.tableName) .where(this.primaryKey, "=", this[this.primaryKey]) diff --git a/es6/lib/model/fetch.js b/es6/lib/model/fetch.js index ad46495..fbbdf79 100644 --- a/es6/lib/model/fetch.js +++ b/es6/lib/model/fetch.js @@ -12,7 +12,7 @@ const fetchByAssociations = { }; function fetchByHasOne(associationName, associations, callback) { - const modelFinder = new ModelFinder(this.constructor.database); + const modelFinder = new ModelFinder(this[symbols.getDatabase]()); const association = associations[associationName]; const ModelClass = association.constructor; @@ -80,7 +80,7 @@ function fetchByHasOne(associationName, associations, callback) { } function fetchWhere(modelClass, key, conditionType, ids, target, callback) { - const modelFinder = new ModelFinder(this.constructor.database); + const modelFinder = new ModelFinder(this[symbols.getDatabase]()); modelFinder .find(modelClass) .where(key, conditionType, ids) @@ -93,14 +93,13 @@ function fetchWhere(modelClass, key, conditionType, ids, target, callback) { } function fetchByHasMany(associationName, associations, callback) { - const modelFinder = new ModelFinder(this.constructor.database); const association = associations[associationName]; if (association.through) { const throughAssociation = associations[association.through]; - modelFinder - .find(throughAssociation.constructor) + throughAssociation.constructor + .find .where(association.foreignId, this[this.primaryKey]) .results((errors, models) => { if(models.length > 0) { @@ -141,7 +140,7 @@ function fetchByHasMany(associationName, associations, callback) { } function fetchByBelongsTo(associationName, associations, callback) { - const modelFinder = new ModelFinder(this.constructor.database); + const modelFinder = new ModelFinder(this[symbols.getDatabase]()); const association = associations[associationName]; if (!this[association.foreignId]) { @@ -161,9 +160,10 @@ function fetchByBelongsTo(associationName, associations, callback) { } function fetchBy(fields = [this.primaryKey], callback = undefined) { - if (!this.constructor.database) { throw new Error("Cannot fetch without Model.database set."); } + let database = this[symbols.getDatabase](); + if (!database) { throw new Error("Cannot fetch without Model.database set."); } - let chain = this.constructor.database + let chain = database .select("*") .from(this.tableName); fields.forEach((field, index) => { diff --git a/es6/lib/model/index.js b/es6/lib/model/index.js index bb821eb..6c1b2f1 100644 --- a/es6/lib/model/index.js +++ b/es6/lib/model/index.js @@ -18,7 +18,7 @@ export default class Model { * @param {Object.} [initialAttributes] Provide default values for attributes by passing a Key-Value Object. * @constructor */ - constructor(initialAttributes) { + constructor(initialAttributes, options) { const _ = privateData(this); _._validations = {}; _._associations = {}; @@ -27,6 +27,10 @@ export default class Model { _._primaryKey = null; _._softDelete = null; + if(options !== undefined) { + _._database = options.database; + } + /** * Define dynamic properties */ @@ -246,6 +250,13 @@ export default class Model { /** * Private Functionality */ + [symbols.getDatabase]() { + let database = privateData(this)._database; + if(!database) { + database = this.constructor.database; + } + return database; + } [symbols.setAttributes](newAttributes) { this[symbols.parseAttributesFromFields](newAttributes); @@ -391,9 +402,21 @@ Object.assign(Model.prototype, { }); Object.defineProperties(Model, { + "database": { + get: function getDatabase() { + let database = this._database; + if(!database) { + database = Model._database; + } + return database; + }, + set: function setDatabase(value) { + this._database = value; + } + }, "find": { get: function modelFind() { - let modelQuery = new ModelFinder(Model.database); + let modelQuery = new ModelFinder(this.database); return modelQuery.find(this); } } diff --git a/es6/lib/model/save.js b/es6/lib/model/save.js index 45000e4..f136c00 100644 --- a/es6/lib/model/save.js +++ b/es6/lib/model/save.js @@ -1,6 +1,7 @@ import flowsync from "flowsync"; import MultiError from "blunder"; import Datetime from "fleming"; +import privateData from "incognito"; import symbols from "./symbols"; //private methods @@ -29,7 +30,7 @@ function saveOrUpdate(callback) { this.createdAt = now.toDate(); let fieldAttributes = this[symbols.getFieldAttributes](); - this.constructor.database + this[symbols.getDatabase]() .insert(fieldAttributes) .into(this.tableName) .results((error, ids) => { @@ -51,7 +52,7 @@ function saveOrUpdate(callback) { } } - this.constructor.database + this[symbols.getDatabase]() .update(updateAttributes) .into(this.tableName) .where(this.primaryKey, "=", this[this.primaryKey]) @@ -90,7 +91,7 @@ function validate(callback) { //public save method export default function save(callback) { - if (!this.constructor.database) { throw new Error("Cannot save without Model.database set."); } + if (!this[symbols.getDatabase]()) { throw new Error("Cannot save without Model.database set."); } flowsync.series([ (next) => { diff --git a/es6/lib/model/symbols.js b/es6/lib/model/symbols.js index bd0b2ef..5095b23 100644 --- a/es6/lib/model/symbols.js +++ b/es6/lib/model/symbols.js @@ -10,5 +10,6 @@ module.exports = { properties: Symbol(), validations: Symbol(), isNew: Symbol(), - fetchBy: Symbol() + fetchBy: Symbol(), + getDatabase: Symbol() }; diff --git a/es6/spec/model.spec.js b/es6/spec/model.spec.js index d8c6e5d..d70ad9b 100644 --- a/es6/spec/model.spec.js +++ b/es6/spec/model.spec.js @@ -335,6 +335,45 @@ describe("Model(attributes, options)", () => { users.length.should.equal(5); }); }); + + describe("(with a different database for a model)", () => { + class Car extends Model {} + let car, + database, + query; + + describe("(static way)", () => { + beforeEach(() => { + database = new Database(databaseConfig); + Car.database = database; + query = database.spy("select * from `cars`", []); + car = new Car(); + }); + + it("should use the specific model class database", (done) => { + Car.find.all.results(() => { + query.callCount.should.equal(1); + done(); + }); + }); + }); + + describe("(instance way)", () => { + beforeEach(() => { + database = new Database(databaseConfig); + Car.database = null; + car = new Car({id: 2}, {database: database}); + query = database.spy("select * from `cars` where `id` = 2 limit 1", []); + }); + + it("should use the specific model instance database", (done) => { + car.fetch(() => { + query.callCount.should.equal(1); + done(); + }); + }); + }); + }); }); }); diff --git a/es6/spec/model/delete.spec.js b/es6/spec/model/delete.spec.js index 0757040..851e619 100644 --- a/es6/spec/model/delete.spec.js +++ b/es6/spec/model/delete.spec.js @@ -192,7 +192,7 @@ describe("Model(attributes, options)", () => { describe("(Model.database not set)", () => { beforeEach(() => { - delete Model.database; + delete Model._database; }); it("should throw an error", () => { diff --git a/es6/spec/model/destroy.spec.js b/es6/spec/model/destroy.spec.js index ddab2b2..df4ff56 100644 --- a/es6/spec/model/destroy.spec.js +++ b/es6/spec/model/destroy.spec.js @@ -192,7 +192,7 @@ // // describe("(Model.database not set)", () => { // beforeEach(() => { -// delete Model.database; +// delete Model._database; // }); // // it("should throw an error", () => { diff --git a/es6/spec/model/fetch.spec.js b/es6/spec/model/fetch.spec.js index c161a21..7f401eb 100644 --- a/es6/spec/model/fetch.spec.js +++ b/es6/spec/model/fetch.spec.js @@ -116,7 +116,7 @@ describe(".fetch(callback)", () => { describe("(Model.database not set)", () => { beforeEach(() => { - delete Model.database; + delete Model._database; }); it("should throw an error", () => { @@ -189,7 +189,7 @@ describe(".fetch(callback)", () => { describe("(Model.database not set)", () => { beforeEach(() => { - delete Model.database; + delete Model._database; }); it("should throw an error", () => { @@ -266,7 +266,7 @@ describe(".fetch(callback)", () => { describe("(Model.database not set)", () => { beforeEach(() => { - delete Model.database; + delete Model._database; }); it("should throw an error", () => { diff --git a/es6/spec/model/save.spec.js b/es6/spec/model/save.spec.js index d3e6061..982bf4d 100644 --- a/es6/spec/model/save.spec.js +++ b/es6/spec/model/save.spec.js @@ -282,7 +282,7 @@ describe("Model(attributes, options)", () => { describe("(Model.database is NOT set)", () => { beforeEach(() => { - delete Model.database; + delete Model._database; }); it("should call back with an error", () => {