Skip to content

Commit

Permalink
fix: fix #263 upsert attributes should use defaultValue while there i… (
Browse files Browse the repository at this point in the history
#265)

* fix: fix #263 upsert attributes should use defaultValue while there is no value assigned

* fix: typo and upsert value validating

Co-authored-by: JimmyDaddy <[email protected]>
  • Loading branch information
JimmyDaddy and JimmyDaddy authored Jan 26, 2022
1 parent 77f47b9 commit 7b6bf3d
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 27 deletions.
22 changes: 18 additions & 4 deletions src/bone.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const Raw = require('./raw');
const { capitalize, camelCase, snakeCase } = require('./utils/string');
const { hookNames, setupSingleHook } = require('./setup_hooks');
const { logger } = require('./utils/index');
const { TIMESTAMP_NAMES, LEGACY_TIMESTAMP_COLUMN_MAP } = require('./constants');

function looseReadonly(props) {
return Object.keys(props).reduce((result, name) => {
Expand Down Expand Up @@ -846,9 +847,13 @@ class Bone {
const data = {};
const Model = this;
const { attributes } = Model;
for (const name in values) {
if (this.hasAttribute(name)) {
data[name] = values[name];
for (const key in attributes) {
const attribute = attributes[key];
if (attribute.primaryKey) continue;
if (values[key] == null && attribute.defaultValue != null) {
data[key] = attribute.defaultValue;
} else if (values[key] !== undefined){
data[key] = values[key];
}
}

Expand Down Expand Up @@ -931,6 +936,15 @@ class Bone {
const attribute = new Attribute(name, attributes[name], options.define);
attributeMap[attribute.columnName] = attribute;
attributes[name] = attribute;
if (TIMESTAMP_NAMES.includes(name)) {
const { columnName } = attribute;
const legacyColumnName = LEGACY_TIMESTAMP_COLUMN_MAP[columnName];
if (!columnMap[columnName] && legacyColumnName && columnMap[legacyColumnName]) {
// correct columname
attribute.columnName = legacyColumnName;
attributeMap[attribute.columnName] = attribute;
}
}
const columnInfo = columnMap[attribute.columnName];
// if datetime or timestamp precision not defined, default to column info
if (columnInfo && attribute.type instanceof DataTypes.DATE && attribute.type.precision == null) {
Expand All @@ -940,7 +954,7 @@ class Bone {

const primaryKey = Object.keys(attributes).find(key => attributes[key].primaryKey);
const timestamps = {};
for (const key of [ 'createdAt', 'updatedAt', 'deletedAt' ]) {
for (const key of TIMESTAMP_NAMES) {
const name = attributes.hasOwnProperty(key) ? key : snakeCase(key);
const attribute = attributes[name];

Expand Down
2 changes: 1 addition & 1 deletion src/collection.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const { AGGREGATOR_MAP } = require('./contants');
const { AGGREGATOR_MAP } = require('./constants');

const AGGREGATORS = Object.values(AGGREGATOR_MAP);
/**
Expand Down
30 changes: 30 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

const AGGREGATOR_MAP = {
count: 'count',
average: 'avg',
minimum: 'min',
maximum: 'max',
sum: 'sum'
};

const LEGACY_TIMESTAMP_MAP = {
gmtCreate: 'createdAt',
gmtModified: 'updatedAt',
gmtDeleted: 'deletedAt',
};

const LEGACY_TIMESTAMP_COLUMN_MAP = {
created_at: 'gmt_create',
updated_at: 'gmt_modified',
deleted_at: 'gmt_deleted',
};

const TIMESTAMP_NAMES = [ 'createdAt', 'updatedAt', 'deletedAt' ];

module.exports = {
AGGREGATOR_MAP,
LEGACY_TIMESTAMP_MAP,
TIMESTAMP_NAMES,
LEGACY_TIMESTAMP_COLUMN_MAP
};
13 changes: 0 additions & 13 deletions src/contants.js

This file was deleted.

7 changes: 1 addition & 6 deletions src/realm.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const { findDriver } = require('./drivers');
const { camelCase } = require('./utils/string');
const sequelize = require('./adapters/sequelize');
const Raw = require('./raw');
const { LEGACY_TIMESTAMP_MAP } = require('./constants');

/**
*
Expand Down Expand Up @@ -39,12 +40,6 @@ async function findModels(dir) {
return models;
}

const LEGACY_TIMESTAMP_MAP = {
gmtCreate: 'createdAt',
gmtModified: 'updatedAt',
gmtDeleted: 'deletedAt',
};

/**
* construct model attributes entirely from column definitions
* @param {Bone} model
Expand Down
2 changes: 1 addition & 1 deletion src/spell.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const { isPlainObject } = require('./utils');
const { IndexHint, INDEX_HINT_TYPE, Hint } = require('./hint');
const { parseObject } = require('./query_object');
const Raw = require('./raw');
const { AGGREGATOR_MAP } = require('./contants');
const { AGGREGATOR_MAP } = require('./constants');

/**
* Parse condition expressions
Expand Down
7 changes: 7 additions & 0 deletions test/integration/suite/basics.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,13 @@ describe('=> Basic', () => {
count = await Tag.count();
assert.equal(count, 1);
});

it('Bone.upsert should assign defaultValue automatically', async () => {
await User.upsert({ email: 'yes@yes', nickname: 'halo' });
const user = await User.findOne({ nickname: 'halo' });
assert.equal(user.attribute('status'), 1);
assert.equal(user.level, 1);
});
});
});

Expand Down
13 changes: 11 additions & 2 deletions test/unit/adapters/sequelize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1495,8 +1495,6 @@ describe('validator should work', () => {

const attributes = {
id: DataTypes.BIGINT,
gmt_create: DataTypes.DATE,
gmt_deleted: DataTypes.DATE,
email: {
type: DataTypes.STRING(256),
allowNull: false,
Expand Down Expand Up @@ -1743,11 +1741,22 @@ describe('validator should work', () => {
status: 1,
}, { validate: false });

await new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, 1000);
});

assert(user);

const users = await User.findAll();

assert.equal(users.length, 1);
assert.equal(users[0].id, user.id);

// created should not be updated
assert.equal(users[0].createdAt.getTime(), user.createdAt.getTime());
assert.notEqual(users[0].level, user.level);
await user.reload();
assert.equal(users[0].level, user.level);
});
Expand Down
15 changes: 15 additions & 0 deletions test/unit/bone.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,21 @@ describe('=> Bone', function() {
// should not override existing one
assert.equal(User.attributes.updatedAt.type.precision, 0);
});

it('should adapt legacy timestamps', async () => {
class User extends Bone {
static attributes = {
createdAt: DATE,
}
}
User.load([
{ columnName: 'id', columnType: 'bigint', dataType: 'bigint', primaryKey: true },
{ columnName: 'gmt_create', columnType: 'timestamp', dataType: 'timestamp' },
]);

assert.ok(User.timestamps.createdAt);
assert.equal(User.attributes.createdAt.columnName, 'gmt_create');
});
});

describe('=> Bone.loadAttribute()', function() {
Expand Down

0 comments on commit 7b6bf3d

Please sign in to comment.