Skip to content

Commit

Permalink
Merge pull request #125 from cbarrese/feature/allow-for-unnamed-params
Browse files Browse the repository at this point in the history
Allow for unnamed attributes. Closes #107
  • Loading branch information
brandongoode committed Apr 14, 2017
2 parents 0de9458 + 9b8cf6c commit 8720e09
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 14 deletions.
8 changes: 8 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,14 @@ Also it is possible to specify wich names that field will use, like in the follo
var schema = new Schema({...}, { throughput: 5, timestamps: {createdAt: 'creationDate', updatedAt: 'lastUpdateDate'});
```
**saveUnknown**: boolean
Specifies that attributes not defined in the _schema_ will be saved and retrieved. This defaults to false.
```js
var schema = new Schema({...}, { saveUnknown: true });
```
## Model API
```js
Expand Down
40 changes: 30 additions & 10 deletions lib/Schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,24 @@ function Schema(obj, options) {
Schema.prototype.toDynamo = function(model) {

var dynamoObj = {};
//debug('toDynamo with schema attributes', this.attributes);
for(var name in this.attributes) {

for(var name in model) {
if(!model.hasOwnProperty(name)){
continue;
}
var attr = this.attributes[name];
attr.setDefault(model);
var dynamoAttr = attr.toDynamo(model[name], undefined, model);
if(dynamoAttr) {
dynamoObj[attr.name] = dynamoAttr;

if(!attr & this.options.saveUnknown) {
attr = Attribute.create(this, name, typeof model[name]);
this.attributes[name] = attr;
}

if(attr) {
attr.setDefault(model);
var dynamoAttr = attr.toDynamo(model[name], undefined, model);
if(dynamoAttr) {
dynamoObj[attr.name] = dynamoAttr;
}
}
}

Expand All @@ -103,10 +114,19 @@ Schema.prototype.toDynamo = function(model) {

Schema.prototype.parseDynamo = function(model, dynamoObj) {

for(var attrName in this.attributes) {
var attrVal = this.attributes[attrName].parseDynamo(dynamoObj[attrName]);
if(attrVal !== undefined && attrVal !== null){
model[attrName] = attrVal;
for(var name in dynamoObj) {
var attr = this.attributes[name];

if(!attr & this.options.saveUnknown) {
attr = Attribute.create(this, name, Object);
this.attributes[name] = attr;
}

if(attr) {
var attrVal = attr.parseDynamo(dynamoObj[name]);
if(attrVal !== undefined && attrVal !== null){
model[name] = attrVal;
}
}
}

Expand Down
97 changes: 95 additions & 2 deletions test/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ dynamoose.local();

var should = require('should');

var Cat, Cat2, Cat3, Cat4;
var Cat, Cat2, Cat3, Cat4, Cat5;

describe('Model', function (){
this.timeout(5000);
this.timeout(15000);


before(function(done) {
Expand Down Expand Up @@ -102,6 +102,25 @@ describe('Model', function (){
}
});

// Create a model with unnamed attributes
Cat5 = dynamoose.model('Cat5',
{
id: {
type: Number,
validate: function (v) { return v > 0; },
default: 888
},
name: {
type: String,
required: true,
default: 'Mittens'
},
owner: String,
},
{
saveUnknown: true
});

done();
});

Expand Down Expand Up @@ -208,6 +227,80 @@ describe('Model', function (){

});

it('Create simple model with unnamed attributes', function (done) {


this.timeout(12000);


Cat5.should.have.property('$__');

Cat5.$__.name.should.eql('test-Cat5');
Cat5.$__.options.should.have.property('saveUnknown', true);

var schema = Cat5.$__.schema;

should.exist(schema);

schema.attributes.id.type.name.should.eql('number');
should(schema.attributes.id.isSet).not.be.ok;
should.exist(schema.attributes.id.default);
should.exist(schema.attributes.id.validator);
should(schema.attributes.id.required).not.be.ok;

schema.attributes.name.type.name.should.eql('string');
schema.attributes.name.isSet.should.not.be.ok;
should.exist(schema.attributes.name.default);
should.not.exist(schema.attributes.name.validator);
should(schema.attributes.name.required).be.ok;

schema.hashKey.should.equal(schema.attributes.id); // should be same object
should.not.exist(schema.rangeKey);

var kitten = new Cat5(
{
id: 2,
name: 'Fluffy',
owner: 'Someone',
unnamedInt: 1,
unnamedString: 'unnamed',
}
);

kitten.id.should.eql(2);
kitten.name.should.eql('Fluffy');

var dynamoObj = schema.toDynamo(kitten);

dynamoObj.should.eql(
{
id: { N: '2' },
name: { S: 'Fluffy' },
owner: { S: 'Someone' },
unnamedInt: { N: '1' },
unnamedString: { S: 'unnamed' },
});

kitten.save(done);

});

it('Get item for model with unnamed attributes', function (done) {

Cat5.get(2, function(err, model) {
should.not.exist(err);
should.exist(model);

model.should.have.property('id', 2);
model.should.have.property('name', 'Fluffy');
model.should.have.property('owner', 'Someone');
model.should.have.property('unnamedInt', 1);
model.should.have.property('unnamedString', 'unnamed');
model.should.have.property('$__');
done();
});
});

it('Get item for model', function (done) {

Cat.get(1, function(err, model) {
Expand Down
4 changes: 2 additions & 2 deletions test/Query.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ describe('Query', function (){
Dog.query('breed').eq('unknown')
.filter('color').not().null().exec()
.then(function (dogs) {
dogs.length.should.eql(5);
dogs.length.should.eql(4);
done();
});
});
Expand All @@ -268,7 +268,7 @@ describe('Query', function (){
.filter('color').not().eq('Brown')
.exec()
.then(function (dogs) {
dogs.length.should.eql(1);
dogs.length.should.eql(2);
dogs[0].ownerId.should.eql(11);
done();
});
Expand Down

2 comments on commit 8720e09

@kjprice
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we know when this will make it to a release? I'd really like to get my hands on this! Thanks :)

@brandongoode
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No ETA on the release date. Hopefully soon, but I can't commit to a date yet.

For now, you can pull directly from the repo. I try to make sure master is always stable, but I would recommend referencing a commit to make sure changes don't impact you.

"dependencies": {
  "package": "git://github.com/automategreen/dynamoose.git#commit"
}

Please sign in to comment.