Skip to content

Instantly share code, notes, and snippets.

@apeace
Created September 19, 2014 13:33
Show Gist options
  • Save apeace/cb20eb269d6b048c7ca0 to your computer and use it in GitHub Desktop.
Save apeace/cb20eb269d6b048c7ca0 to your computer and use it in GitHub Desktop.
var expect = require('expect.js');
var model = require('./qmodel.js');
describe('qmodel', function () {
var createPersonModel = function () {
function Person (props) {
model.extend(this, Person, props);
}
Person.fields = {
'name': model.StringField(),
'dob': model.DateField(),
'heightInCm': model.IntField()
};
model.makeModel(Person);
return Person;
};
var createPersonInstance = function () {
var Person = createPersonModel();
var person = Person.from({
'name': 'Fred',
'dob': '2014-09-18',
'heightInCm': 200
});
return person;
};
it('Can create a model', function () {
expect(createPersonModel()).to.be.a('function');
});
it('Can create an instance of a model', function () {
var person = createPersonInstance();
expect(person.name).to.equal('Fred');
// expect(person.dob).to.equal(???);
expect(person.heightInCm).to.equal(200);
});
it('Can copy an instance of a model', function () {
var person1 = createPersonInstance();
var person2 = person1.copy();
person2.name = 'Charles';
expect(person1.name).to.equal('Fred');
expect(person2.name).to.equal('Charles');
});
it('Can copy really fast? (100,000 iterations)', function () {
var person1 = createPersonInstance();
var person2;
for (var i = 0; i < 100000; i++) {
person2 = person1.copy();
person2.heightInCm = i;
person1 = person2; // don't just copy the same object over and over
}
expect(person2.heightInCm).to.equal(i-1);
});
it('Can copy an instance with modifications', function () {
var person1 = createPersonInstance();
var person2 = person1.with({
'name': 'Charles'
});
expect(person1.name).to.equal('Fred');
expect(person2.name).to.equal('Charles');
});
it('Can copy with modifications really fast? (100,000 iterations)', function () {
var person1 = createPersonInstance();
var person2;
for (var i = 0; i < 100000; i++) {
person2 = person1.with({heightInCm: i});
person1 = person2; // don't just copy the same object over and over
}
expect(person2.heightInCm).to.equal(i-1);
});
});
var model = module.exports = {};
model.extend = function (modelInstance, modelFn, props) {
var field;
for (var i = 0; i < modelFn.fieldList.length; i++) {
field = modelFn.fieldList[i];
modelInstance[field] = props[field] || null;
}
};
model.makeModel = function (fn) {
if (!fn.fields) {
throw new Error('The model must have fields set');
}
fn.fieldList = Object.keys(fn.fields);
fn.from = function (obj) {
fn.sanityCheckFields(obj);
return new fn(obj);
};
fn.sanityCheckFields = function (props) {
for (var field in props) {
if (!fn.fields[field]) {
throw new Error('Invalid field ' + field);
}
// TODO sanity checking of each field type
}
};
fn.prototype.toObj = function () {
var fields = fn.fieldList;
var obj = {};
var field;
for (var i = 0; i < fields.length; i++) {
field = fields[i];
obj[field] = this[field];
}
return obj;
};
fn.prototype.toJSON = function () {
return JSON.stringify(this.toObj());
};
fn.prototype.copy = function () {
return new fn(this);
};
fn.prototype.set = function (props) {
for (var field in props) {
this[field] = props[field];
}
};
fn.prototype.with = function (props) {
fn.sanityCheckFields(props);
var copy = this.copy();
copy.set(props);
return copy;
};
};
model.StringField = function () {
return true; // TODO
};
model.DateField = function () {
return true; // TODO
};
model.IntField = function () {
return true; // TODO
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment