simplifying the model structure, again

This commit is contained in:
Tim Griesser 2013-06-01 10:47:41 -04:00
parent f783adbe7f
commit 983c171fb0
23 changed files with 463 additions and 488 deletions

View File

@ -76,8 +76,8 @@
client: 'sqlite3',
connection: {
filename: './core/shared/data/tests.db'
},
debug: true
}
// debug: true
},
development: {

View File

@ -8,6 +8,7 @@
api = require('../../shared/api'),
ghost = new Ghost(),
dataProvider = ghost.dataProvider,
adminNavbar,
adminControllers;
@ -170,7 +171,7 @@
});
},
'dbpopulate': function (req, res) {
ghost.dataProvider().populateData(function (error) {
dataProvider.populateData(function (error) {
if (error) {
req.flash('error', error);
} else {
@ -180,7 +181,7 @@
});
},
'newUser': function (req, res) {
ghost.dataProvider().addNewUser(req, function (error) {
dataProvider.addNewUser(req, function (error) {
if (error) {
req.flash('error', error);
} else {

View File

@ -14,10 +14,7 @@
_ = require('underscore'),
Polyglot = require('node-polyglot'),
JsonDataProvider = require('./shared/models/dataProvider.json'),
jsonDataProvider = new JsonDataProvider(),
BookshelfDataProvider = require('./shared/models/dataProvider.bookshelf'),
bookshelfDataProvider = new BookshelfDataProvider(),
models = require('./shared/models'),
ExampleFilter = require('../content/plugins/exampleFilters'),
Ghost,
instance,
@ -49,8 +46,14 @@
polyglot;
if (!instance) {
// this.init();
instance = this;
// Holds the filters
this.filterCallbacks = [];
// Holds the filter hooks (that are built in to Ghost Core)
this.filters = [];
plugin = new ExampleFilter(instance).init();
app = express();
@ -64,8 +67,8 @@
_.extend(instance, {
app: function () { return app; },
config: function () { return config; },
globals: function () { return instance.globalsData; }, // there's no management here to be sure this has loaded
dataProvider: function () { return bookshelfDataProvider; },
globals: function () { return instance.globalConfig; }, // there's no management here to be sure this has loaded
dataProvider: models,
statuses: function () { return statuses; },
polyglot: function () { return polyglot; },
plugin: function () { return plugin; },
@ -84,29 +87,11 @@
return instance;
};
Ghost.prototype.init = function() {
var initGlobals = jsonDataProvider.save(config.blogData).then(function () {
return jsonDataProvider.findAll().then(function (data) {
// We must have an instance to be able to call ghost.init(), right?
instance.globalsData = data;
});
});
return when.all([initGlobals, instance.dataProvider().init()]);
Ghost.prototype.init = function () {
this.globalConfig = config.blogData;
return when.all([instance.dataProvider.init()]);
};
/**
* Holds the filters
* @type {Array}
*/
Ghost.prototype.filterCallbacks = [];
/**
* Holds the filter hooks (that are built in to Ghost Core)
* @type {Array}
*/
Ghost.prototype.filters = [];
/**
* @param {string} name
* @param {Function} fn

View File

@ -13,6 +13,7 @@
_ = require('underscore'),
ghost = new Ghost(),
dataProvider = ghost.dataProvider,
posts,
users,
settings,
@ -23,50 +24,50 @@
// takes filter / pagination parameters
// returns a list of posts in a json response
browse: function (options) {
return ghost.dataProvider().posts.findAll(options);
return dataProvider.Post.findAll(options);
},
// takes an identifier (id or slug?)
// returns a single post in a json response
read: function (args) {
return ghost.dataProvider().posts.findOne(args);
return dataProvider.Post.findOne(args);
},
// takes a json object with all the properties which should be updated
// returns the resulting post in a json response
edit: function (postData) {
return ghost.dataProvider().posts.edit(postData);
return dataProvider.Post.edit(postData);
},
// takes a json object representing a post,
// returns the resulting post in a json response
add: function (postData) {
return ghost.dataProvider().posts.add(postData);
return dataProvider.Post.add(postData);
},
// takes an identifier (id or slug?)
// returns a json response with the id of the deleted post
destroy: function (args) {
return ghost.dataProvider().posts.destroy(args.id);
return dataProvider.Post.destroy(args.id);
}
};
// # Users
users = {
add: function (postData) {
return ghost.dataProvider().users.add(postData);
return dataProvider.User.add(postData);
},
check: function (postData) {
return ghost.dataProvider().users.check(postData);
return dataProvider.User.check(postData);
}
};
// # Settings
settings = {
browse: function (options) {
return ghost.dataProvider().settings.browse(options);
return dataProvider.Setting.browse(options);
},
read: function (options) {
return ghost.dataProvider().settings.read(options.key);
return dataProvider.Setting.read(options.key);
},
edit: function (options) {
return ghost.dataProvider().settings.edit(options);
return dataProvider.Setting.edit(options);
}
};

View File

@ -5,7 +5,7 @@
var when = require('when'),
knex = require('../../models/knex_init'),
knex = require('../../models/base').Knex,
fixtures = require('../fixtures/001'),
up,
down;

View File

@ -0,0 +1,96 @@
(function () {
"use strict";
var GhostBookshelf,
Bookshelf = require('bookshelf'),
config = require('../../../config');
// Initializes Bookshelf as its own instance, so we can modify the Models and not mess up
// others' if they're using the library outside of ghost.
GhostBookshelf = Bookshelf.Initialize('ghost', config.database[process.env.NODE_ENV || 'development']);
// The Base Model which other Ghost objects will inherit from,
// including some convenience functions as static properties on the model.
GhostBookshelf.Model = GhostBookshelf.Model.extend({
// Base prototype properties will go here
}, {
/**
* Naive find all
* @param options (optional)
*/
findAll: function (options) {
options = options || {};
return GhostBookshelf.Collection.forge([], {model: this}).fetch(options);
},
browse: function () {
return this.findAll.apply(this, arguments);
},
/**
* Naive find one where args match
* @param args
* @param options (optional)
*/
findOne: function (args, options) {
options = options || {};
return this.forge(args).fetch(options);
},
read: function () {
return this.findOne.apply(this, arguments);
},
/**
* Naive edit
* @param editedObj
* @param options (optional)
*/
edit: function (editedObj, options) {
options = options || {};
return this.forge({id: editedObj.id}).fetch(options).then(function (foundObj) {
return foundObj.set(editedObj).save();
});
},
update: function () {
return this.edit.apply(this, arguments);
},
/**
* Naive create
* @param editedObj
* @param options (optional)
*/
add: function (newObj, options) {
options = options || {};
return this.forge(newObj).save(options);
},
create: function () {
return this.add.apply(this, arguments);
},
/**
* Naive destroy
* @param _identifier
* @param options (optional)
*/
destroy: function (_identifier, options) {
options = options || {};
return this.forge({id: _identifier}).destroy(options);
},
'delete': function () {
return this.destroy.apply(this, arguments);
}
});
module.exports = GhostBookshelf;
}());

View File

@ -1,74 +0,0 @@
/*global require, module */
(function () {
"use strict";
var _ = require('underscore'),
BookshelfBase;
/**
* The base class for interacting with bookshelf models/collections.
* Provides naive implementations of CRUD/BREAD operations.
*/
BookshelfBase = function (model, collection) {
// Bind the 'this' value for all our functions since they get messed
// up by the when.call
_.bindAll(this, 'findAll', 'browse', 'findOne', 'read', 'edit', 'add', 'destroy');
this.model = model;
this.collection = collection;
};
/**
* Naive find all
* @param args (optional)
* @param opts (optional)
*/
BookshelfBase.prototype.findAll = BookshelfBase.prototype.browse = function (opts) {
opts = opts || {};
return this.collection.forge().fetch(opts);
};
/**
* Naive find one where args match
* @param args
* @param opts (optional)
*/
BookshelfBase.prototype.findOne = BookshelfBase.prototype.read = function (args, opts) {
opts = opts || {};
return this.model.forge(args).fetch(opts);
};
/**
* Naive edit
* @param editedObj
* @param opts (optional)
*/
BookshelfBase.prototype.edit = BookshelfBase.prototype.update = function (editedObj, opts) {
opts = opts || {};
return this.model.forge({id: editedObj.id}).fetch(opts).then(function (foundObj) {
return foundObj.set(editedObj).save();
});
};
/**
* Naive add
* @param newObj
* @param opts (optional)
*/
BookshelfBase.prototype.add = BookshelfBase.prototype.create = function (newObj, opts) {
opts = opts || {};
return this.model.forge(newObj).save(opts);
};
/**
* Naive destroy
* @param _identifier
* @param opts (optional)
*/
BookshelfBase.prototype.destroy = BookshelfBase.prototype['delete'] = function (_identifier, opts) {
opts = opts || {};
return this.model.forge({id: _identifier}).destroy(opts);
};
module.exports = BookshelfBase;
}());

View File

@ -1,52 +0,0 @@
/**
* Provides access to data via the Bookshelf ORM
*/
/*globals module, require, process */
(function () {
"use strict";
var _ = require('underscore'),
knex = require('./knex_init'),
PostsProvider = require('./dataProvider.bookshelf.posts'),
UsersProvider = require('./dataProvider.bookshelf.users'),
SettingsProvider = require('./dataProvider.bookshelf.settings'),
DataProvider,
instance,
defaultOptions = {
autoInit: false
};
DataProvider = function (options) {
options = _.defaults(options || {}, defaultOptions);
if (!instance) {
instance = this;
if (options.autoInit) {
this.init();
}
}
return instance;
};
DataProvider.prototype.init = function () {
return knex.Schema.hasTable('posts').then(null, function () {
// Simple bootstraping of the data model for now.
var migration = require('../data/migration/001');
return migration.down().then(function () {
return migration.up();
});
}).then(function () {
console.log('DataProvider ready');
});
};
DataProvider.prototype.posts = new PostsProvider();
DataProvider.prototype.users = new UsersProvider();
DataProvider.prototype.settings = new SettingsProvider();
module.exports = DataProvider;
}());

View File

@ -1,91 +0,0 @@
(function () {
"use strict";
var _ = require('underscore'),
util = require('util'),
models = require('./models'),
Bookshelf = require('bookshelf'),
BaseProvider = require('./dataProvider.bookshelf.base'),
PostsProvider;
/**
* The Posts data provider implementation for Bookshelf.
*/
PostsProvider = function () {
BaseProvider.call(this, models.Post, models.Posts);
};
util.inherits(PostsProvider, BaseProvider);
/**
* Find results by page - returns an object containing the
* information about the request (page, limit), along with the
* info needed for pagination (pages, total).
*
* {
* posts: [
* {...}, {...}, {...}
* ],
* page: __,
* limit: __,
* pages: __,
* total: __
* }
*
* @params opts
*/
PostsProvider.prototype.findPage = function (opts) {
var postCollection;
// Allow findPage(n)
if (!_.isObject(opts)) {
opts = {page: opts};
}
opts = _.defaults(opts || {}, {
page: 1,
limit: 15,
where: null
});
postCollection = this.collection.forge();
// If there are where conditionals specified, add those
// to the query.
if (opts.where) {
postCollection.query('where', opts.where);
}
// Set the limit & offset for the query, fetching
// with the opts (to specify any eager relations, etc.)
// Omitting the `page`, `limit`, `where` just to be sure
// aren't used for other purposes.
return postCollection
.query('limit', opts.limit)
.query('offset', opts.limit * (opts.page - 1))
.fetch(_.omit(opts, 'page', 'limit', 'where'))
.then(function (collection) {
var qb;
// After we're done, we need to figure out what
// the limits are for the pagination values.
qb = Bookshelf.Knex(_.result(collection, 'tableName'));
if (opts.where) {
qb.where(opts.where);
}
return qb.count(_.result(collection, 'idAttribute')).then(function (resp) {
var totalPosts = resp[0].aggregate;
return {
posts: collection.toJSON(),
page: opts.page,
limit: opts.limit,
pages: Math.ceil(totalPosts / opts.limit),
total: totalPosts
};
});
});
};
module.exports = PostsProvider;
}());

View File

@ -1,37 +0,0 @@
(function () {
"use strict";
var _ = require('underscore'),
when = require('when'),
util = require('util'),
models = require('./models'),
BaseProvider = require('./dataProvider.bookshelf.base'),
SettingsProvider;
/**
* The Posts data provider implementation for Bookshelf.
*/
SettingsProvider = function () {
BaseProvider.call(this, models.Setting, models.Settings);
};
util.inherits(SettingsProvider, BaseProvider);
SettingsProvider.prototype.read = function (_key) {
// Allow for just passing the key instead of attributes
if (_.isString(_key)) {
_key = { key: _key };
}
return BaseProvider.prototype.read.call(this, _key);
};
SettingsProvider.prototype.edit = function (_data) {
return when.all(_.map(_data, function (value, key) {
return this.model.forge({ key: key }).fetch().then(function (setting) {
return setting.set('value', value).save();
});
}, this));
};
module.exports = SettingsProvider;
}());

View File

@ -1,70 +0,0 @@
(function () {
"use strict";
var util = require('util'),
_ = require('underscore'),
bcrypt = require('bcrypt-nodejs'),
models = require('./models.js'),
when = require('when'),
nodefn = require('when/node/function'),
BaseProvider = require('./dataProvider.bookshelf.base.js'),
UsersProvider;
/**
* The Users data provider implementation for Bookshelf.
*/
UsersProvider = function () {
BaseProvider.call(this, models.User, models.Users);
};
util.inherits(UsersProvider, BaseProvider);
/**
* Naive user add
* @param _user
*
* Hashes the password provided before saving to the database.
*/
UsersProvider.prototype.add = function (_user) {
var self = this,
// Clone the _user so we don't expose the hashed password unnecessarily
userData = _.extend({}, _user);
return self.model.forge({email_address: userData.email_address}).fetch().then(function (user) {
if (!!user.attributes.email_address) {
when.reject(new Error('A user with that email address already exists.'));
}
return nodefn.call(bcrypt.hash, _user.password, null, null).then(function (hash) {
userData.password = hash;
return BaseProvider.prototype.add.call(self, userData);
});
});
};
/**
* User check
* @param _userdata
*
* Finds the user by email, and check's the password
*/
UsersProvider.prototype.check = function (_userdata) {
return this.model.forge({
email_address: _userdata.email
}).fetch().then(function (user) {
if (!!user.attributes.email_address) {
return nodefn.call(bcrypt.compare, _userdata.pw, user.get('password')).then(function (matched) {
if (!matched) {
return when.reject(new Error('Passwords do not match'));
}
return user;
});
}
return when.reject(new Error('We do not have a record for such user.'));
});
};
module.exports = UsersProvider;
}());

View File

@ -1,35 +0,0 @@
/**
* Dummy dataProvider returns hardcoded JSON data until we finish migrating settings data to a datastore
*/
/*globals module, require */
(function () {
"use strict";
var _ = require('underscore'),
when = require('when'),
DataProvider,
instance;
DataProvider = function () {
if (!instance) {
instance = this;
_.extend(instance, {
data: [],
findAll: function() {
return when(instance.data);
},
save: function (globals) {
_.each(globals, function (global, key) {
instance.data[key] = global;
}, instance);
return when(globals);
}
});
}
return instance;
};
module.exports = DataProvider;
}());

View File

@ -0,0 +1,26 @@
/*global require, module */
(function () {
"use strict";
var GhostBookshelf = require('./base'),
knex = GhostBookshelf.Knex;
module.exports = {
Post: require('./post').Post,
User: require('./user').User,
Setting: require('./setting').Setting,
init: function () {
return knex.Schema.hasTable('posts').then(null, function () {
// Simple bootstraping of the data model for now.
var migration = require('../data/migration/001');
return migration.down().then(function () {
return migration.up();
});
}).then(function () {
console.log('models loaded');
});
}
};
}());

View File

@ -1,11 +0,0 @@
/*global require, module, process */
(function () {
"use strict";
var knex = require('knex'),
config = require('../../../config');
knex.Initialize(config.database[process.env.NODE_ENV || 'development']);
module.exports = knex;
}());

134
core/shared/models/post.js Normal file
View File

@ -0,0 +1,134 @@
(function () {
"use strict";
var Post,
Posts,
_ = require('underscore'),
Showdown = require('showdown'),
converter = new Showdown.converter(),
User = require('./user').User,
GhostBookshelf = require('./base');
Post = GhostBookshelf.Model.extend({
tableName: 'posts',
hasTimestamps: true,
initialize: function () {
this.on('creating', this.creating, this);
this.on('saving', this.saving, this);
},
saving: function () {
if (!this.get('title')) {
throw new Error('Post title cannot be blank');
}
this.set('content_html', converter.makeHtml(this.get('content')));
// refactoring of ghost required in order to make these details available here
// this.set('language', this.get('language') || ghost.config().defaultLang);
// this.set('status', this.get('status') || ghost.statuses().draft);
},
creating: function () {
if (!this.get('slug')) {
this.generateSlug();
}
},
generateSlug: function () {
return this.set('slug', this.get('title').replace(/\:/g, '').replace(/\s/g, '-').toLowerCase());
},
user: function () {
return this.belongsTo(User, 'created_by');
}
}, {
/**
* Find results by page - returns an object containing the
* information about the request (page, limit), along with the
* info needed for pagination (pages, total).
*
* {
* posts: [
* {...}, {...}, {...}
* ],
* page: __,
* limit: __,
* pages: __,
* total: __
* }
*
* @params opts
*/
findPage: function (opts) {
var postCollection;
// Allow findPage(n)
if (!_.isObject(opts)) {
opts = {page: opts};
}
opts = _.defaults(opts || {}, {
page: 1,
limit: 15,
where: null
});
postCollection = Posts.forge();
// If there are where conditionals specified, add those
// to the query.
if (opts.where) {
postCollection.query('where', opts.where);
}
// Set the limit & offset for the query, fetching
// with the opts (to specify any eager relations, etc.)
// Omitting the `page`, `limit`, `where` just to be sure
// aren't used for other purposes.
return postCollection
.query('limit', opts.limit)
.query('offset', opts.limit * (opts.page - 1))
.fetch(_.omit(opts, 'page', 'limit', 'where'))
.then(function (collection) {
var qb;
// After we're done, we need to figure out what
// the limits are for the pagination values.
qb = GhostBookshelf.Knex(_.result(collection, 'tableName'));
if (opts.where) {
qb.where(opts.where);
}
return qb.count(_.result(collection, 'idAttribute')).then(function (resp) {
var totalPosts = resp[0].aggregate;
return {
posts: collection.toJSON(),
page: opts.page,
limit: opts.limit,
pages: Math.ceil(totalPosts / opts.limit),
total: totalPosts
};
});
});
}
});
Posts = GhostBookshelf.Collection.extend({
model: Post
});
module.exports = {
Post: Post,
Posts: Posts
};
}());

View File

@ -0,0 +1,45 @@
(function () {
"use strict";
var Setting,
Settings,
GhostBookshelf = require('./base'),
_ = require('underscore'),
when = require('when');
Setting = GhostBookshelf.Model.extend({
tableName: 'settings',
hasTimestamps: true
}, {
read: function (_key) {
// Allow for just passing the key instead of attributes
if (!_.isObject(_key)) {
_key = { key: _key };
}
return GhostBookshelf.Model.read.call(this, _key);
},
edit: function (_data) {
return when.all(_.map(_data, function (value, key) {
return this.forge({ key: key }).fetch().then(function (setting) {
return setting.set('value', value).save();
});
}, this));
}
});
Settings = GhostBookshelf.Collection.extend({
model: Setting
});
module.exports = {
Setting: Setting,
Settings: Settings
};
}());

View File

@ -0,0 +1,78 @@
(function () {
"use strict";
var User,
Users,
_ = require('underscore'),
when = require('when'),
nodefn = require('when/node/function'),
bcrypt = require('bcrypt-nodejs'),
Posts = require('./post').Posts,
GhostBookshelf = require('./base');
User = GhostBookshelf.Model.extend({
tableName: 'users',
hasTimestamps: true,
posts: function () {
return this.hasMany(Posts, 'created_by');
}
}, {
/**
* Naive user add
* @param _user
*
* Hashes the password provided before saving to the database.
*/
add: function (_user) {
var User = this,
// Clone the _user so we don't expose the hashed password unnecessarily
userData = _.extend({}, _user);
return this.forge({email_address: userData.email_address}).fetch().then(function (user) {
if (!!user.attributes.email_address) {
when.reject(new Error('A user with that email address already exists.'));
}
return nodefn.call(bcrypt.hash, _user.password, null, null).then(function (hash) {
userData.password = hash;
return GhostBookshelf.Model.add.call(User, userData);
});
});
},
/**
* User check
* @param _userdata
*
* Finds the user by email, and check's the password
*/
check: function (_userdata) {
return this.forge({
email_address: _userdata.email
}).fetch({require: true}).then(function (user) {
return nodefn.call(bcrypt.compare, _userdata.pw, user.get('password')).then(function (matched) {
if (!matched) {
return when.reject(new Error('Passwords do not match'));
}
return user;
});
});
}
});
Users = GhostBookshelf.Collection.extend({
model: User
});
module.exports = {
User: User,
Users: Users
};
}());

View File

@ -6,21 +6,20 @@
var _ = require("underscore"),
should = require('should'),
helpers = require('./helpers'),
PostProvider = require('../../shared/models/dataProvider.bookshelf.posts');
Models = require('../../shared/models');
describe('Bookshelf PostsProvider', function () {
describe('Bookshelf Post Model', function () {
var posts;
var PostModel = Models.Post;
beforeEach(function (done) {
helpers.resetData().then(function () {
posts = new PostProvider();
done();
}, done);
});
it('can browse', function (done) {
posts.browse().then(function (results) {
PostModel.browse().then(function (results) {
should.exist(results);
results.length.should.equal(2);
@ -32,14 +31,14 @@
it('can read', function (done) {
var firstPost;
posts.browse().then(function (results) {
PostModel.browse().then(function (results) {
should.exist(results);
results.length.should.be.above(0);
firstPost = results.models[0];
return posts.read({slug: firstPost.attributes.slug});
return PostModel.read({slug: firstPost.attributes.slug});
}).then(function (found) {
should.exist(found);
@ -52,7 +51,7 @@
it('can edit', function (done) {
var firstPost;
posts.browse().then(function (results) {
PostModel.browse().then(function (results) {
should.exist(results);
@ -60,7 +59,7 @@
firstPost = results.models[0];
return posts.edit({id: firstPost.id, title: "new title"});
return PostModel.edit({id: firstPost.id, title: "new title"});
}).then(function (edited) {
@ -79,7 +78,7 @@
content: 'Test Content 1'
};
posts.add(newPost).then(function (createdPost) {
PostModel.add(newPost).then(function (createdPost) {
should.exist(createdPost);
createdPost.attributes.title.should.equal(newPost.title, "title is correct");
@ -92,7 +91,7 @@
it('can delete', function (done) {
var firstPostId;
posts.browse().then(function (results) {
PostModel.browse().then(function (results) {
should.exist(results);
@ -100,11 +99,11 @@
firstPostId = results.models[0].id;
return posts.destroy(firstPostId);
return PostModel.destroy(firstPostId);
}).then(function () {
return posts.browse();
return PostModel.browse();
}).then(function (newResults) {
var ids, hasDeletedId;
@ -126,7 +125,7 @@
helpers.insertMorePosts().then(function () {
return posts.findPage({page: 2});
return PostModel.findPage({page: 2});
}).then(function (paginationResult) {
@ -138,7 +137,7 @@
paginationResult.pages.should.equal(4);
return posts.findPage({page: 5});
return PostModel.findPage({page: 5});
}).then(function (paginationResult) {
@ -150,7 +149,7 @@
paginationResult.pages.should.equal(4);
return posts.findPage({limit: 30});
return PostModel.findPage({limit: 30});
}).then(function (paginationResult) {
@ -162,7 +161,7 @@
paginationResult.pages.should.equal(2);
return posts.findPage({limit: 10, page: 2, where: {language: 'fr'}});
return PostModel.findPage({limit: 10, page: 2, where: {language: 'fr'}});
}).then(function (paginationResult) {

View File

@ -6,21 +6,20 @@
var _ = require("underscore"),
should = require('should'),
helpers = require('./helpers'),
SettingProvider = require('../../shared/models/dataProvider.bookshelf.settings');
Models = require('../../shared/models');
describe('Bookshelf SettingsProvider', function () {
describe('Bookshelf Setting Model', function () {
var settings;
var SettingModel = Models.Setting;
beforeEach(function (done) {
helpers.resetData().then(function () {
settings = new SettingProvider();
done();
});
}, done);
});
it('can browse', function (done) {
settings.browse().then(function (results) {
SettingModel.browse().then(function (results) {
should.exist(results);
@ -33,7 +32,7 @@
it('can read', function (done) {
var firstSetting;
settings.browse().then(function (results) {
SettingModel.browse().then(function (results) {
should.exist(results);
@ -41,7 +40,7 @@
firstSetting = results.models[0];
return settings.read(firstSetting.attributes.key);
return SettingModel.read(firstSetting.attributes.key);
}).then(function (found) {
@ -58,7 +57,7 @@
var firstPost,
toEdit = {};
settings.browse().then(function (results) {
SettingModel.browse().then(function (results) {
should.exist(results);
@ -70,7 +69,7 @@
// key/value pairs
toEdit[firstPost.attributes.key] = "new value";
return settings.edit(toEdit);
return SettingModel.edit(toEdit);
}).then(function (edited) {
@ -94,7 +93,7 @@
editedPost,
toEdit = {};
settings.browse().then(function (results) {
SettingModel.browse().then(function (results) {
should.exist(results);
@ -108,7 +107,7 @@
toEdit[firstPost.attributes.key] = "new value1";
toEdit[secondPost.attributes.key] = "new value2";
return settings.edit(toEdit);
return SettingModel.edit(toEdit);
}).then(function (edited) {
@ -137,7 +136,7 @@
value: 'Test Content 1'
};
settings.add(newSetting).then(function (createdSetting) {
SettingModel.add(newSetting).then(function (createdSetting) {
should.exist(createdSetting);
@ -151,7 +150,7 @@
it('can delete', function (done) {
var firstSettingId;
settings.browse().then(function (results) {
SettingModel.browse().then(function (results) {
should.exist(results);
@ -159,11 +158,11 @@
firstSettingId = results.models[0].id;
return settings.destroy(firstSettingId);
return SettingModel.destroy(firstSettingId);
}).then(function () {
return settings.browse();
return SettingModel.browse();
}).then(function (newResults) {

View File

@ -6,22 +6,21 @@
var _ = require('underscore'),
should = require('should'),
helpers = require('./helpers'),
UserProvider = require('../../shared/models/dataProvider.bookshelf.users');
Models = require('../../shared/models');
describe('Bookshelf UsersProvider', function () {
describe('Bookshelf User Model', function () {
var users;
var UserModel = Models.User;
beforeEach(function (done) {
helpers.resetData().then(function () {
users = new UserProvider();
done();
});
}, done);
});
it('can browse', function (done) {
users.browse().then(function (results) {
UserModel.browse().then(function (results) {
should.exist(results);
@ -35,7 +34,7 @@
it('can read', function (done) {
var firstUser;
users.browse().then(function (results) {
UserModel.browse().then(function (results) {
should.exist(results);
@ -43,7 +42,7 @@
firstUser = results.models[0];
return users.read({email_address: firstUser.attributes.email_address});
return UserModel.read({email_address: firstUser.attributes.email_address});
}).then(function (found) {
@ -60,7 +59,7 @@
it('can edit', function (done) {
var firstUser;
users.browse().then(function (results) {
UserModel.browse().then(function (results) {
should.exist(results);
@ -68,7 +67,7 @@
firstUser = results.models[0];
return users.edit({id: firstUser.id, url: "some.newurl.com"});
return UserModel.edit({id: firstUser.id, url: "some.newurl.com"});
}).then(function (edited) {
@ -87,7 +86,7 @@
email_address: "test@test1.com"
};
users.add(userData).then(function (createdUser) {
UserModel.add(userData).then(function (createdUser) {
should.exist(createdUser);
@ -101,7 +100,7 @@
it('can delete', function (done) {
var firstUserId;
users.browse().then(function (results) {
UserModel.browse().then(function (results) {
should.exist(results);
@ -109,11 +108,11 @@
firstUserId = results.models[0].id;
return users.destroy(firstUserId);
return UserModel.destroy(firstUserId);
}).then(function () {
return users.browse();
return UserModel.browse();
}).then(function (newResults) {
var ids, hasDeletedId;

View File

@ -1,20 +0,0 @@
/*globals describe, beforeEach, it*/
(function () {
"use strict";
var should = require('should'),
DataProvider = require('../../shared/models/dataProvider.json');
describe("dataProvider.json", function () {
it("is a singleton", function () {
var provider1 = new DataProvider(),
provider2 = new DataProvider();
should.strictEqual(provider1, provider2);
});
});
}());

View File

@ -20,26 +20,28 @@
it("uses init() to initialize", function (done) {
var ghost = new Ghost(),
fakeDataProvider = {
init: function() {
init: function () {
return when.resolve();
}
},
dataProviderInitSpy = sinon.spy(fakeDataProvider, "init");
dataProviderInitSpy = sinon.spy(fakeDataProvider, "init"),
oldDataProvder = ghost.dataProvider;
// Stub out the dataProvider
sinon.stub(ghost, "dataProvider", function () {
return fakeDataProvider;
});
ghost.dataProvider = fakeDataProvider;
should.not.exist(ghost.globals());
ghost.init().then(function () {
should.exist(ghost.globals());
dataProviderInitSpy.called.should.equal(true);
ghost.dataProvider = oldDataProvder;
done();
}, done);
}).then(null, done);
});
});

View File

@ -4,7 +4,7 @@
// Use 'testing' Ghost config; unless we are running on travis (then show queries for debugging)
process.env.NODE_ENV = process.env.TRAVIS ? 'travis' : 'testing';
var knex = require('knex'),
var knex = require('../../shared/models/base').Knex,
migrations = {
one: require("../../shared/data/migration/001")
},