Skip to content

Commit

Permalink
fix: reload attribute if instance updated with jsonMerge
Browse files Browse the repository at this point in the history
  • Loading branch information
cyjake committed Sep 13, 2024
1 parent 20c0761 commit a61c5b9
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![Build Status](https://github.com/cyjake/leoric/actions/workflows/nodejs.yml/badge.svg)](https://github.com/cyjake/leoric/actions/workflows/nodejs.yml)
[![codecov](https://codecov.io/gh/cyjake/leoric/branch/master/graph/badge.svg?token=OZZWTZTDS1)](https://codecov.io/gh/cyjake/leoric)

Leoric is an object-relational mapping for Node.js, which is heavily influenced by Active Record of Ruby on Rails. See the [documentation](https://leoric.js.org) for detail.
Leoric is an object-relational mapping library for Node.js, which is heavily influenced by Active Record of Ruby on Rails. See the [documentation](https://leoric.js.org) for detail.

## Usage

Expand Down
1 change: 1 addition & 0 deletions docs/_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ description: > # this means to ignore newlines until "baseurl:"
An object-relational mapping for Node.js which is heavily influenced by Active Record.
# Build settings
permalink: pretty
kramdown:
toc_levels: 2..3
theme: jekyll-theme-primer
Expand Down
43 changes: 35 additions & 8 deletions src/bone.js
Original file line number Diff line number Diff line change
Expand Up @@ -682,15 +682,26 @@ class Bone {
* @memberof Bone
*/
async jsonMerge(name, jsonValue, options = {}) {
const raw = new Raw(`JSON_MERGE_PATCH(${name}, '${JSON.stringify(jsonValue)}')`);
const affectedRows = await this.update({ [name]: raw }, options);
const Model = this.constructor;
const { primaryKey, shardingKey } = Model;
if (this[primaryKey] == null) throw new Error(`unset primary key ${primaryKey}`);

const { preserve, ...restOptions } = options;
const where = { [primaryKey]: this[primaryKey] };
if (shardingKey) where[shardingKey] = this[shardingKey];

const affectedRows = await Model.jsonMerge(where, { [name]: jsonValue }, options);
// reload only the updated attribute, incase overwriting others
const spell = Model._find(where, restOptions).$select(name).$get(0);
spell.scopes = [];
const instance = await spell;
if (instance) this.attribute(name, instance.attribute(name));

return affectedRows;
}

async jsonMergePreserve(name, jsonValue, options = {}) {
const raw = new Raw(`JSON_MERGE_PRESERVE(${name}, '${JSON.stringify(jsonValue)}')`);
const affectedRows = await this.update({ [name]: raw }, options);
return affectedRows;
return await this.jsonMerge(name, jsonValue, { ...options, preserve: true });
}

/**
Expand All @@ -707,9 +718,10 @@ class Bone {
const { fields = [] } = options;
if (typeof values === 'object') {
for (const name in values) {
if (values[name] !== undefined && this.hasAttribute(name) && (!fields.length || fields.includes(name))) {
const value = values[name];
if (value !== undefined && !(value instanceof Raw) && this.hasAttribute(name) && (!fields.length || fields.includes(name))) {
// exec custom setters in case it exist
this[name] = values[name];
this[name] = value;
changes[name] = this.attribute(name);
}
}
Expand Down Expand Up @@ -767,7 +779,8 @@ class Bone {
return await spell.later(result => {
// sync changes (changes has been formatted by custom setters, use this.attribute(name, value) directly)
for (const key in changes) {
this.attribute(key, changes[key]);
const value = changes[key];
if (!(value instanceof Raw)) this.attribute(key, value);
}
this.syncRaw();
return result.affectedRows;
Expand Down Expand Up @@ -1560,6 +1573,20 @@ class Bone {
});
}

static jsonMerge(conditions, values = {}, options = {}) {
const { preserve, ...restOptions } = options;
const method = preserve ? 'JSON_MERGE_PRESERVE' : 'JSON_MERGE_PATCH';
const data = { ...values };
for (const [name, value] of Object.entries(values)) {
data[name] = new Raw(`${method}(${name}, '${JSON.stringify(value)}')`);
}
return this.update(conditions, data, restOptions);
}

static jsonMergePreserve(conditions, values = {}, options = {}) {
return this.jsonMerge(conditions, values, { ...options, preserve: true });

Check warning on line 1587 in src/bone.js

View check run for this annotation

Codecov / codecov/patch

src/bone.js#L1587

Added line #L1587 was not covered by tests
}

/**
* Remove any record that matches `conditions`.
* - If `forceDelete` is true, `DELETE` records from database permanently.
Expand Down
5 changes: 1 addition & 4 deletions test/integration/suite/json.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,12 @@ describe('=> Basic', () => {
await gen.update({ extra: { a: 1 } });
assert.equal(gen.extra.a, 1);
await gen.jsonMerge('extra', { b: 2, a: 3 });
await gen.reload();
assert.equal(gen.extra.a, 3);
assert.equal(gen.extra.b, 2);

const gen2 = await Gen.create({ name: 'gen2', extra: { test: 1 }});
assert.equal(gen2.extra.test, 1);
await gen2.jsonMerge('extra', { url: 'https://www.wanxiang.art/?foo=' });
await gen2.reload();
assert.equal(gen2.extra.url, 'https://www.wanxiang.art/?foo=');
});

Expand All @@ -53,6 +51,7 @@ describe('=> Basic', () => {

const sql = new Raw(`JSON_MERGE_PATCH(extra, '${JSON.stringify({ url: 'https://www.taobao.com/?id=1' })}')`);
await gen.update({extra: sql});
assert.ok(!(gen.extra instanceof Raw));
await gen.reload();
assert.equal(gen.extra.url, 'https://www.taobao.com/?id=1');
});
Expand All @@ -63,12 +62,10 @@ describe('=> Basic', () => {
await gen.update({ extra: { a: 1 } });
assert.equal(gen.extra.a, 1);
await gen.jsonMergePreserve('extra', { b: 2, a: 3 });
await gen.reload();
assert.deepEqual(gen.extra.a, [1, 3]);

await gen.jsonMerge('extra', { url: 'https://wanxiang.art/?foo=' });
await gen.jsonMergePreserve('extra', { url: 'https://www.wanxiang.art/?foo=' });
await gen.reload();
assert.deepEqual(gen.extra.url, ['https://wanxiang.art/?foo=', 'https://www.wanxiang.art/?foo=']);
});
});
Expand Down

0 comments on commit a61c5b9

Please sign in to comment.