2
1
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2023-12-13 21:00:40 +01:00

Merge pull request #3213 from hswolff/lazy-load-models

Preparation for lazy loading of models
This commit is contained in:
Hannah Wolfe 2014-07-11 15:29:46 +01:00
commit ef1207cc0d
22 changed files with 113 additions and 92 deletions

View file

@ -7,12 +7,14 @@ var path = require('path'),
when = require('when'),
url = require('url'),
_ = require('lodash'),
knex = require('knex'),
requireTree = require('../require-tree').readAll,
theme = require('./theme'),
configUrl = require('./url'),
ghostConfig = {},
appRoot = path.resolve(__dirname, '../../../'),
corePath = path.resolve(appRoot, 'core/');
corePath = path.resolve(appRoot, 'core/'),
knexInstance;
// Are we using sockets? Custom socket or the default?
function getSocket() {
@ -51,7 +53,14 @@ function updateConfig(config) {
// Otherwise default to default content path location
contentPath = ghostConfig.paths.contentPath || path.resolve(appRoot, 'content');
if (!knexInstance && ghostConfig.database) {
knexInstance = knex(ghostConfig.database);
}
_.merge(ghostConfig, {
database: {
knex: knexInstance
},
paths: {
'appRoot': appRoot,
'subdir': subdir,

View file

@ -1,7 +1,7 @@
var _ = require('lodash'),
when = require('when'),
versioning = require('../versioning'),
knex = require('../../models/base').knex,
config = require('../../config'),
utils = require('../utils'),
excludedTables = ['sessions'],
@ -13,7 +13,7 @@ exporter = function () {
tables = results[1],
selectOps = _.map(tables, function (name) {
if (excludedTables.indexOf(name) < 0) {
return knex(name).select();
return config().database.knex(name).select();
}
});

View file

@ -2,13 +2,7 @@ var when = require('when'),
sequence = require('when/sequence'),
_ = require('lodash'),
utils = require('../../utils'),
Post = require('../../models/post').Post,
Tag = require('../../models/tag').Tag,
Role = require('../../models/role').Role,
Permission = require('../../models/permission').Permission,
Client = require('../../models/client').Client,
Permissions = require('../../models/permission').Permissions,
User = require('../../models/user').User,
models = require('../../models'),
populateFixtures,
updateFixtures;
@ -175,7 +169,15 @@ var fixtures = {
populateFixtures = function () {
var ops = [],
relations = [];
relations = [],
Post = models.Post,
Tag = models.Tag,
Role = models.Role,
Permission = models.Permission,
Permissions = models.Permissions,
Client = models.Client,
User = models.User;
_.each(fixtures.posts, function (post) {
ops.push(function () {return Post.add(post, {user: 1}); });
@ -288,7 +290,12 @@ populateFixtures = function () {
updateFixtures = function () {
var ops = [],
relations = [],
adminUser;
adminUser,
Role = models.Role,
Permission = models.Permission,
Permissions = models.Permissions,
Client = models.Client,
User = models.User;
_.each(fixtures.permissions003, function (permission) {
ops.push(function () {return Permission.add(permission, {user: 1}); });

View file

@ -4,12 +4,10 @@ var _ = require('lodash'),
fs = require('fs'),
nodefn = require('when/node'),
errors = require('../../errors'),
client = require('../../models/base').client,
knex = require('../../models/base').knex,
sequence = require('when/sequence'),
versioning = require('../versioning'),
Settings = require('../../models/settings').Settings,
models = require('../../models'),
fixtures = require('../fixtures'),
schema = require('../schema').tables,
dataExport = require('../export'),
@ -143,7 +141,7 @@ migrateUpFreshDb = function () {
// Load the fixtures
return fixtures.populateFixtures().then(function () {
// Initialise the default settings
return Settings.populateDefaults();
return models.Settings.populateDefaults();
});
});
};
@ -151,8 +149,10 @@ migrateUpFreshDb = function () {
// This function changes the type of posts.html and posts.markdown columns to mediumtext. Due to
// a wrong datatype in schema.js some installations using mysql could have been created using the
// data type text instead of mediumtext.
// For details see: https://github.com/TryGhost/Ghost/issues/1947
// For details see: https://github.com/TryGhost/Ghost/issues/1947
function checkMySQLPostTable() {
var knex = config().database.knex;
return knex.raw("SHOW FIELDS FROM posts where Field ='html' OR Field = 'markdown'").then(function (response) {
return _.flatten(_.map(response[0], function (entry) {
if (entry.Type.toLowerCase() !== 'mediumtext') {
@ -178,6 +178,7 @@ migrateUp = function () {
var deleteCommands,
addCommands,
oldTables,
client = config().database.client,
addColumns = [],
modifyUniCommands = [],
commands = [];
@ -244,4 +245,4 @@ module.exports = {
reset: reset,
migrateUp: migrateUp,
migrateUpFreshDb: migrateUpFreshDb
};
};

View file

@ -1,8 +1,7 @@
var _ = require('lodash'),
when = require('when'),
knex = require('../../models/base').knex,
config = require('../../config'),
schema = require('../schema').tables,
client = require('../../models/base').client,
sqlite3 = require('./sqlite3'),
mysql = require('./mysql'),
pgsql = require('./pgsql');
@ -42,25 +41,25 @@ function addTableColumn(tablename, table, columnname) {
}
function addColumn(table, column) {
return knex.schema.table(table, function (t) {
return config().database.knex.schema.table(table, function (t) {
addTableColumn(table, t, column);
});
}
function addUnique(table, column) {
return knex.schema.table(table, function (table) {
return config().database.knex.schema.table(table, function (table) {
table.unique(column);
});
}
function dropUnique(table, column) {
return knex.schema.table(table, function (table) {
return config().database.knex.schema.table(table, function (table) {
table.dropUnique(column);
});
}
function createTable(table) {
return knex.schema.createTable(table, function (t) {
return config().database.knex.schema.createTable(table, function (t) {
var columnKeys = _.keys(schema[table]);
_.each(columnKeys, function (column) {
return addTableColumn(table, t, column);
@ -69,10 +68,12 @@ function createTable(table) {
}
function deleteTable(table) {
return knex.schema.dropTableIfExists(table);
return config().database.knex.schema.dropTableIfExists(table);
}
function getTables() {
var client = config().database.client;
if (client === 'sqlite3') {
return sqlite3.getTables();
}
@ -86,6 +87,8 @@ function getTables() {
}
function getIndexes(table) {
var client = config().database.client;
if (client === 'sqlite3') {
return sqlite3.getIndexes(table);
}
@ -99,6 +102,8 @@ function getIndexes(table) {
}
function getColumns(table) {
var client = config().database.client;
if (client === 'sqlite3') {
return sqlite3.getColumns(table);
}

View file

@ -1,8 +1,8 @@
var _ = require('lodash'),
knex = require('../../models/base').knex;
var _ = require('lodash'),
config = require('../../config');
function getTables() {
return knex.raw('show tables').then(function (response) {
return config().database.knex.raw('show tables').then(function (response) {
return _.flatten(_.map(response[0], function (entry) {
return _.values(entry);
}));
@ -10,13 +10,13 @@ function getTables() {
}
function getIndexes(table) {
return knex.raw('SHOW INDEXES from ' + table).then(function (response) {
return config().database.knex.raw('SHOW INDEXES from ' + table).then(function (response) {
return _.flatten(_.pluck(response[0], 'Key_name'));
});
}
function getColumns(table) {
return knex.raw('SHOW COLUMNS FROM ' + table).then(function (response) {
return config().database.knex.raw('SHOW COLUMNS FROM ' + table).then(function (response) {
return _.flatten(_.pluck(response[0], 'Field'));
});
}

View file

@ -1,8 +1,8 @@
var _ = require('lodash'),
knex = require('../../models/base').knex;
var _ = require('lodash'),
config = require('../../config');
function getTables() {
return knex.raw("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'").then(function (response) {
return config().database.knex.raw("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'").then(function (response) {
return _.flatten(_.pluck(response.rows, 'table_name'));
});
}
@ -13,7 +13,7 @@ function getIndexes(table) {
+ " WHERE t.oid = ix.indrelid and i.oid = ix.indexrelid and"
+ " a.attrelid = t.oid and a.attnum = ANY(ix.indkey) and t.relname = '" + table + "'";
return knex.raw(selectIndexes).then(function (response) {
return config().database.knex.raw(selectIndexes).then(function (response) {
return _.flatten(_.pluck(response.rows, 'index_name'));
});
}
@ -21,7 +21,7 @@ function getIndexes(table) {
function getColumns(table) {
var selectIndexes = "SELECT column_name FROM information_schema.columns WHERE table_name = '" + table + "'";
return knex.raw(selectIndexes).then(function (response) {
return config().database.knex.raw(selectIndexes).then(function (response) {
return _.flatten(_.pluck(response.rows, 'column_name'));
});
}

View file

@ -1,8 +1,8 @@
var _ = require('lodash'),
knex = require('../../models/base').knex;
var _ = require('lodash'),
config = require('../../config');
function getTables() {
return knex.raw("select * from sqlite_master where type = 'table'").then(function (response) {
return config().database.knex.raw("select * from sqlite_master where type = 'table'").then(function (response) {
return _.reject(_.pluck(response, 'tbl_name'), function (name) {
return name === 'sqlite_sequence';
});
@ -10,14 +10,14 @@ function getTables() {
}
function getIndexes(table) {
return knex.raw("pragma index_list('" + table + "')").then(function (response) {
return config().database.knex.raw("pragma index_list('" + table + "')").then(function (response) {
return _.flatten(_.pluck(response, 'name'));
});
}
function getColumns(table) {
return knex.raw("pragma table_info('" + table + "')").then(function (response) {
return config().database.knex.raw("pragma table_info('" + table + "')").then(function (response) {
return _.flatten(_.pluck(response, 'name'));
});
}

View file

@ -1,6 +1,6 @@
var _ = require('lodash'),
errors = require('../../errors'),
knex = require('../../models/base').knex,
config = require('../../config'),
defaultSettings = require('../default-settings'),
@ -23,6 +23,8 @@ function getDefaultDatabaseVersion() {
// The migration version number according to the database
// This is what the database is currently at and may need to be updated
function getDatabaseVersion() {
var knex = config().database.knex;
return knex.schema.hasTable('settings').then(function (exists) {
// Check for the current version from the settings table
if (exists) {
@ -52,7 +54,7 @@ function getDatabaseVersion() {
}
function setDatabaseVersion() {
return knex('settings')
return config().database.knex('settings')
.where('key', 'databaseVersion')
.update({ 'value': defaultDatabaseVersion });
}

View file

@ -16,6 +16,7 @@ var crypto = require('crypto'),
helpers = require('./helpers'),
mailer = require('./mail'),
middleware = require('./middleware'),
migrations = require('./data/migration'),
models = require('./models'),
permissions = require('./permissions'),
apps = require('./apps'),
@ -214,6 +215,12 @@ function init(server) {
return builtFilesExist().then(function () {
// Initialise the models
return models.init();
}).then(function () {
// Initialize migrations
return migrations.init();
}).then(function () {
// Populate any missing default settings
return models.Settings.populateDefaults();
}).then(function () {
// Initialize the settings cache
return api.init();

View file

@ -6,7 +6,6 @@
// accesses the models directly. All other parts of Ghost, including the blog frontend, admin UI, and apps are only
// allowed to access data via the API.
var bookshelf = require('bookshelf'),
knex = require('knex'),
when = require('when'),
moment = require('moment'),
_ = require('lodash'),
@ -21,8 +20,7 @@ var bookshelf = require('bookshelf'),
// ### ghostBookshelf
// Initializes a new Bookshelf instance called ghostBookshelf, for reference elsewhere in Ghost.
ghostBookshelf = bookshelf(knex(config().database));
ghostBookshelf.client = config().database.client;
ghostBookshelf = bookshelf(config().database.knex);
// ### ghostBookshelf.Model
// The Base Model which other Ghost objects will inherit from,

View file

@ -1,5 +1,4 @@
var migrations = require('../data/migration'),
_ = require('lodash'),
var _ = require('lodash'),
when = require('when');
module.exports = {
@ -7,6 +6,7 @@ module.exports = {
User: require('./user').User,
Role: require('./role').Role,
Permission: require('./permission').Permission,
Permissions: require('./permission').Permissions,
Settings: require('./settings').Settings,
Tag: require('./tag').Tag,
Base: require('./base'),
@ -19,7 +19,7 @@ module.exports = {
Refreshtoken: require('./refreshtoken').Refreshtoken,
init: function () {
return migrations.init();
return true;
},
// ### deleteAllContent
// Delete all content from the database (posts, tags, tags_posts)

View file

@ -1,12 +1,10 @@
var _ = require('lodash'),
Models = require('../models'),
errors = require('../errors'),
User = Models.User,
App = Models.App;
errors = require('../errors');
var effective = {
user: function (id) {
return User.findOne({id: id}, { include: ['permissions', 'roles', 'roles.permissions'] })
return Models.User.findOne({id: id}, { include: ['permissions', 'roles', 'roles.permissions'] })
.then(function (foundUser) {
var seenPerms = {},
rolePerms = _.map(foundUser.related('roles').models, function (role) {
@ -41,7 +39,7 @@ var effective = {
},
app: function (appName) {
return App.findOne({name: appName}, { withRelated: ['permissions'] })
return Models.App.findOne({name: appName}, { withRelated: ['permissions'] })
.then(function (foundApp) {
if (!foundApp) {
return [];

View file

@ -4,9 +4,7 @@
var _ = require('lodash'),
when = require('when'),
Models = require('../models'),
objectTypeModelMap = require('./objectTypeModelMap'),
effectivePerms = require('./effective'),
PermissionsProvider = Models.Permission,
init,
refresh,
canThis,
@ -52,6 +50,9 @@ CanThisResult = function () {
};
CanThisResult.prototype.buildObjectTypeHandlers = function (obj_types, act_type, context, permissionLoad) {
// @TODO: remove this lazy require
var objectTypeModelMap = require('./objectTypeModelMap');
// Iterate through the object types, i.e. ['post', 'tag', 'user']
return _.reduce(obj_types, function (obj_type_handlers, obj_type) {
// Grab the TargetModel through the objectTypeModelMap
@ -201,7 +202,7 @@ canThis = function (context) {
init = refresh = function () {
// Load all the permissions
return PermissionsProvider.findAll().then(function (perms) {
return Models.Permission.findAll().then(function (perms) {
var seenActions = {};
exported.actionsMap = {};

View file

@ -70,7 +70,7 @@ function updateCheckData() {
data.ghost_version = currentVersion;
data.node_version = process.versions.node;
data.env = process.env.NODE_ENV;
data.database_type = require('./models/base').client;
data.database_type = config().database.client;
data.email_transport = mailConfig && (mailConfig.options && mailConfig.options.service ? mailConfig.options.service : mailConfig.transport);
return when.settle(ops).then(function (descriptors) {

View file

@ -4,8 +4,7 @@ var testUtils = require('../../utils'),
_ = require("lodash"),
// Stuff we are testing
Models = require('../../../server/models'),
knex = require('../../../server/models/base').knex;
Models = require('../../../server/models');
describe('App Fields Model', function () {

View file

@ -4,8 +4,7 @@ var testUtils = require('../../utils'),
_ = require("lodash"),
// Stuff we are testing
Models = require('../../../server/models'),
knex = require('../../../server/models/base').knex;
Models = require('../../../server/models');
describe('App Setting Model', function () {

View file

@ -5,8 +5,7 @@ var testUtils = require('../../utils'),
_ = require("lodash"),
// Stuff we are testing
Models = require('../../../server/models'),
knex = require('../../../server/models/base').knex;
Models = require('../../../server/models');
describe('App Model', function () {

View file

@ -5,7 +5,7 @@ var testUtils = require('../../utils'),
// Stuff we are testing
Models = require('../../../server/models'),
knex = require('../../../server/models/base').knex;
config = require('../../../server/config');
describe('Settings Model', function () {
@ -178,7 +178,7 @@ describe('Settings Model', function () {
describe('populating defaults from settings.json', function (done) {
beforeEach(function (done) {
knex('settings').truncate().then(function () {
config().database.knex('settings').truncate().then(function () {
done();
});
});

View file

@ -8,7 +8,7 @@ var testUtils = require('../utils'),
_ = require('lodash'),
// Stuff we are testing
knex = require('../../server/models/base').knex,
config = require('../../server/config'),
migration = require('../../server/data/migration'),
versioning = require('../../server/data/versioning'),
exporter = require('../../server/data/export'),
@ -23,7 +23,8 @@ describe('Import', function () {
should.exist(exporter);
should.exist(importer);
var sandbox;
var sandbox,
knex = config().database.knex;
beforeEach(function (done) {
sandbox = sinon.sandbox.create();

View file

@ -9,10 +9,7 @@ var testUtils = require('../utils'),
// Stuff we are testing
permissions = require('../../server/permissions'),
effectivePerms = require('../../server/permissions/effective'),
Models = require('../../server/models'),
UserProvider = Models.User,
PermissionsProvider = Models.Permission,
PostProvider = Models.Post;
Models = require('../../server/models');
describe('Permissions', function () {
@ -63,7 +60,7 @@ describe('Permissions', function () {
object_type: obj
};
return PermissionsProvider.add(newPerm, {user: 1});
return Models.Permission.add(newPerm, {user: 1});
},
createTestPermissions = function () {
var createActions = _.map(testPerms, function (testPerm) {
@ -102,7 +99,7 @@ describe('Permissions', function () {
it('can add user to role', function (done) {
var existingUserRoles;
UserProvider.findOne({id: 1}, { withRelated: ['roles'] }).then(function (foundUser) {
Models.User.findOne({id: 1}, { withRelated: ['roles'] }).then(function (foundUser) {
var testRole = new Models.Role({
name: 'testrole1',
description: 'testrole1 description'
@ -118,7 +115,7 @@ describe('Permissions', function () {
return foundUser.roles().attach(testRole);
});
}).then(function () {
return UserProvider.findOne({id: 1}, { withRelated: ['roles'] });
return Models.User.findOne({id: 1}, { withRelated: ['roles'] });
}).then(function (updatedUser) {
should.exist(updatedUser);
@ -129,7 +126,7 @@ describe('Permissions', function () {
});
it('can add user permissions', function (done) {
UserProvider.findOne({id: 1}, { withRelated: ['permissions']}).then(function (testUser) {
Models.User.findOne({id: 1}, { withRelated: ['permissions']}).then(function (testUser) {
var testPermission = new Models.Permission({
name: 'test edit posts',
action_type: 'edit',
@ -142,7 +139,7 @@ describe('Permissions', function () {
return testUser.permissions().attach(testPermission);
});
}).then(function () {
return UserProvider.findOne({id: 1}, { include: ['permissions']});
return Models.User.findOne({id: 1}, { include: ['permissions']});
}).then(function (updatedUser) {
should.exist(updatedUser);
@ -210,7 +207,7 @@ describe('Permissions', function () {
createTestPermissions()
.then(permissions.init)
.then(function () {
return UserProvider.findOne({id: 1});
return Models.User.findOne({id: 1});
})
.then(function (foundUser) {
var canThisResult = permissions.canThis(foundUser);
@ -233,7 +230,7 @@ describe('Permissions', function () {
createTestPermissions()
.then(permissions.init)
.then(function () {
return UserProvider.findOne({id: 1});
return Models.User.findOne({id: 1});
})
.then(function (foundUser) {
var newPerm = new Models.Permission({
@ -247,7 +244,7 @@ describe('Permissions', function () {
});
})
.then(function () {
return UserProvider.findOne({id: 1}, { withRelated: ['permissions']});
return Models.User.findOne({id: 1}, { withRelated: ['permissions']});
})
.then(function (updatedUser) {
@ -266,13 +263,13 @@ describe('Permissions', function () {
it('can use permissable function on Model to allow something', function (done) {
var testUser,
permissableStub = sandbox.stub(PostProvider, 'permissable', function () {
permissableStub = sandbox.stub(Models.Post, 'permissable', function () {
return when.resolve();
});
testUtils.insertAuthorUser()
.then(function () {
return UserProvider.findAll();
return Models.User.findAll();
})
.then(function (foundUser) {
testUser = foundUser.models[1];
@ -295,13 +292,13 @@ describe('Permissions', function () {
it('can use permissable function on Model to forbid something', function (done) {
var testUser,
permissableStub = sandbox.stub(PostProvider, 'permissable', function () {
permissableStub = sandbox.stub(Models.Post, 'permissable', function () {
return when.reject();
});
testUtils.insertAuthorUser()
.then(function () {
return UserProvider.findAll();
return Models.User.findAll();
})
.then(function (foundUser) {
testUser = foundUser.models[1];
@ -345,10 +342,10 @@ describe('Permissions', function () {
it('does not allow an app to edit a post without permission', function (done) {
// Change the author of the post so the author override doesn't affect the test
PostProvider.edit({'author_id': 2}, {id: 1})
Models.Post.edit({'author_id': 2}, {id: 1})
.then(function (updatedPost) {
// Add user permissions
return UserProvider.findOne({id: 1})
return Models.User.findOne({id: 1})
.then(function (foundUser) {
var newPerm = new Models.Permission({
name: 'app test edit post',

View file

@ -6,7 +6,6 @@ var knex = require('../../server/models/base').knex,
fs = require('fs-extra'),
path = require('path'),
migration = require("../../server/data/migration/"),
Settings = require('../../server/models/settings').Settings,
DataGenerator = require('./fixtures/data-generator'),
API = require('./api'),
fork = require('./fork');
@ -33,7 +32,6 @@ function insertMorePosts(max) {
var lang,
status,
posts = [],
promises = [],
i, j, k = 0;
max = max || 50;
@ -88,8 +86,7 @@ function insertMorePostsTags(max) {
}
function insertDefaultUser() {
var user,
userRoles;
var user;
user = DataGenerator.forKnex.createUser(DataGenerator.Content.users[0]);
@ -173,9 +170,10 @@ function insertAppWithFields() {
return knex('apps').insert(apps, 'id')
.then(function (results) {
var appId = results[0];
var appId = results[0],
i;
for (var i = 0; i < app_fields.length; i++) {
for (i = 0; i < app_fields.length; i++) {
app_fields[i].app_id = appId;
}
@ -228,6 +226,6 @@ module.exports = {
DataGenerator: DataGenerator,
API: API,
fork: fork
};