velocious 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/spec/database/record/translation-fallbacks-spec.js +24 -0
- package/spec/dummy/src/config/configuration.example.js +4 -0
- package/spec/dummy/src/config/configuration.peakflow.js +4 -0
- package/src/configuration.js +9 -3
- package/src/database/drivers/base.js +16 -0
- package/src/database/drivers/mysql/index.js +3 -2
- package/src/database/drivers/mysql/sql/insert.js +0 -25
- package/src/database/drivers/sqlite/base.js +61 -2
- package/src/database/drivers/sqlite/index.native.js +1 -0
- package/src/database/drivers/sqlite/index.web.js +1 -0
- package/src/database/drivers/sqlite/sql/insert.js +0 -25
- package/src/database/query/index.js +16 -0
- package/src/database/query/insert-base.js +59 -3
- package/src/database/record/index.js +46 -20
- package/src/templates/configuration.js +4 -0
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Dummy from "../../dummy/index.js"
|
|
2
|
+
import Task from "../../dummy/src/models/task.js"
|
|
3
|
+
|
|
4
|
+
describe("Record - create", () => {
|
|
5
|
+
it("creates a new simple record", async () => {
|
|
6
|
+
await Dummy.run(async () => {
|
|
7
|
+
const task = new Task({name: "Test task"})
|
|
8
|
+
const project = task.buildProject({nameDe: "Test projekt"})
|
|
9
|
+
|
|
10
|
+
expect(project.name()).toEqual("Test projekt")
|
|
11
|
+
expect(project.nameEn()).toEqual(undefined)
|
|
12
|
+
expect(project.nameDe()).toEqual("Test projekt")
|
|
13
|
+
|
|
14
|
+
await task.save()
|
|
15
|
+
|
|
16
|
+
const sameTask = await Task.preload({project: {translations: true}}).find(task.id())
|
|
17
|
+
const sameProject = sameTask.project()
|
|
18
|
+
|
|
19
|
+
expect(sameProject.name()).toEqual("Test projekt")
|
|
20
|
+
expect(sameProject.nameEn()).toEqual(undefined)
|
|
21
|
+
expect(sameProject.nameDe()).toEqual("Test projekt")
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
})
|
package/src/configuration.js
CHANGED
|
@@ -8,7 +8,7 @@ export default class VelociousConfiguration {
|
|
|
8
8
|
return this.velociousConfiguration
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
constructor({database, debug, directory, initializeModels, locale, locales, ...restArgs}) {
|
|
11
|
+
constructor({database, debug, directory, initializeModels, locale, localeFallbacks, locales, ...restArgs}) {
|
|
12
12
|
restArgsError(restArgs)
|
|
13
13
|
|
|
14
14
|
if (!initializeModels) throw new Error("initializeModels wasn't given")
|
|
@@ -19,6 +19,7 @@ export default class VelociousConfiguration {
|
|
|
19
19
|
this._initializeModels = initializeModels
|
|
20
20
|
this._isInitialized = false
|
|
21
21
|
this.locale = locale
|
|
22
|
+
this.localeFallbacks = localeFallbacks
|
|
22
23
|
this.locales = locales
|
|
23
24
|
this.modelClasses = {}
|
|
24
25
|
}
|
|
@@ -31,7 +32,7 @@ export default class VelociousConfiguration {
|
|
|
31
32
|
return this.databasePool
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
getDatabasePoolType
|
|
35
|
+
getDatabasePoolType() {
|
|
35
36
|
const poolTypeClass = digg(this, "database", "default", "master", "poolType")
|
|
36
37
|
|
|
37
38
|
if (!poolTypeClass) {
|
|
@@ -41,7 +42,7 @@ export default class VelociousConfiguration {
|
|
|
41
42
|
return poolTypeClass
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
getDirectory
|
|
45
|
+
getDirectory() {
|
|
45
46
|
if (!this._directory) {
|
|
46
47
|
this._directory = process.cwd()
|
|
47
48
|
}
|
|
@@ -49,6 +50,11 @@ export default class VelociousConfiguration {
|
|
|
49
50
|
return this._directory
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
getLocaleFallbacks = () => this.localeFallbacks
|
|
54
|
+
setLocaleFallbacks(newLocaleFallbacks) {
|
|
55
|
+
this.localeFallbacks = newLocaleFallbacks
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
getLocale() {
|
|
53
59
|
if (typeof this.locale == "function") {
|
|
54
60
|
return this.locale()
|
|
@@ -78,6 +78,22 @@ export default class VelociousDatabaseDriversBase {
|
|
|
78
78
|
return false
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
async transaction(callback) {
|
|
82
|
+
await this.query("BEGIN TRANSACTION")
|
|
83
|
+
|
|
84
|
+
let result
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
result = await callback()
|
|
88
|
+
await this.query("COMMIT")
|
|
89
|
+
} catch (error) {
|
|
90
|
+
this.query("ROLLBACK")
|
|
91
|
+
throw error
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result
|
|
95
|
+
}
|
|
96
|
+
|
|
81
97
|
async update(...args) {
|
|
82
98
|
const sql = this.updateSql(...args)
|
|
83
99
|
|
|
@@ -93,8 +93,9 @@ export default class VelociousDatabaseDriversMysql extends Base{
|
|
|
93
93
|
return deleteInstruction.toSql()
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
insertSql(
|
|
97
|
-
const
|
|
96
|
+
insertSql(args) {
|
|
97
|
+
const insertArgs = Object.assign({driver: this}, args)
|
|
98
|
+
const insert = new Insert(insertArgs)
|
|
98
99
|
|
|
99
100
|
return insert.toSql()
|
|
100
101
|
}
|
|
@@ -1,29 +1,4 @@
|
|
|
1
1
|
import InsertBase from "../../../query/insert-base.js"
|
|
2
2
|
|
|
3
3
|
export default class VelociousDatabaseConnectionDriversMysqlSqlInsert extends InsertBase {
|
|
4
|
-
toSql() {
|
|
5
|
-
let sql = `INSERT INTO ${this.getOptions().quoteTableName(this.tableName)} (`
|
|
6
|
-
let count = 0
|
|
7
|
-
|
|
8
|
-
for (let columnName in this.data) {
|
|
9
|
-
if (count > 0) sql += ", "
|
|
10
|
-
|
|
11
|
-
sql += this.getOptions().quoteColumnName(columnName)
|
|
12
|
-
count++
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
sql += ") VALUES ("
|
|
16
|
-
count = 0
|
|
17
|
-
|
|
18
|
-
for (let columnName in this.data) {
|
|
19
|
-
if (count > 0) sql += ", "
|
|
20
|
-
|
|
21
|
-
sql += this.getOptions().quote(this.data[columnName])
|
|
22
|
-
count++
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
sql += ")"
|
|
26
|
-
|
|
27
|
-
return sql
|
|
28
|
-
}
|
|
29
4
|
}
|
|
@@ -34,8 +34,8 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
34
34
|
return createTable.toSql()
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
deleteSql = (
|
|
38
|
-
insertSql = (
|
|
37
|
+
deleteSql = (args) => new Delete(Object.assign({driver: this}, args)).toSql()
|
|
38
|
+
insertSql = (args) => new Insert(Object.assign({driver: this}, args)).toSql()
|
|
39
39
|
|
|
40
40
|
async getTableByName(tableName) {
|
|
41
41
|
const result = await this.query(`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${this.quote(tableName)} LIMIT 1`)
|
|
@@ -64,6 +64,53 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
64
64
|
return tables
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
async insertMultiple(...args) {
|
|
68
|
+
if (this.supportsMultipleInsertValues()) {
|
|
69
|
+
return await this.insertMultipleWithSingleInsert(...args)
|
|
70
|
+
} else {
|
|
71
|
+
return await this.insertMultipleWithTransaction(...args)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
supportsMultipleInsertValues() {
|
|
76
|
+
if (this.versionMajor >= 4) return true
|
|
77
|
+
if (this.versionMajor == 3 && this.versionMinor >= 8) return true
|
|
78
|
+
if (this.versionMajor == 3 && this.versionMinor == 7 && this.versionPatch >= 11) return true
|
|
79
|
+
|
|
80
|
+
return false
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async insertMultipleWithSingleInsert(tableName, columns, rows) {
|
|
84
|
+
const sql = new Insert({columns, driver: this, rows, tableName}).toSql()
|
|
85
|
+
|
|
86
|
+
return await this.query(sql)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async insertMultipleWithTransaction(tableName, columns, rows) {
|
|
90
|
+
const sqls = []
|
|
91
|
+
|
|
92
|
+
for (const row of rows) {
|
|
93
|
+
const data = []
|
|
94
|
+
|
|
95
|
+
for (const columnIndex in columns) {
|
|
96
|
+
const columnName = columns[columnIndex]
|
|
97
|
+
const value = row[columnIndex]
|
|
98
|
+
|
|
99
|
+
data[columnName] = value
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const insertSql = this.insertSql({tableName, data})
|
|
103
|
+
|
|
104
|
+
sqls.push(insertSql)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
await this.transaction(async () => {
|
|
108
|
+
for (const sql of sqls) {
|
|
109
|
+
await this.query(sql)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
67
114
|
async lastInsertID() {
|
|
68
115
|
const result = await this.query("SELECT LAST_INSERT_ROWID() AS last_insert_id")
|
|
69
116
|
|
|
@@ -80,6 +127,18 @@ export default class VelociousDatabaseDriversSqliteBase extends Base {
|
|
|
80
127
|
|
|
81
128
|
queryToSql = (query) => new QueryParser({query}).toSql()
|
|
82
129
|
|
|
130
|
+
async registerVersion() {
|
|
131
|
+
const versionResult = await this.query("SELECT sqlite_version() AS version")
|
|
132
|
+
|
|
133
|
+
this.version = versionResult[0].version
|
|
134
|
+
|
|
135
|
+
const versionParts = this.version.split(".")
|
|
136
|
+
|
|
137
|
+
this.versionMajor = versionParts[0]
|
|
138
|
+
this.versionMinor = versionParts[1]
|
|
139
|
+
this.versionPatch = versionParts[2]
|
|
140
|
+
}
|
|
141
|
+
|
|
83
142
|
escape(value) {
|
|
84
143
|
const type = typeof value
|
|
85
144
|
|
|
@@ -24,6 +24,7 @@ export default class VelociousDatabaseDriversSqliteWeb extends Base {
|
|
|
24
24
|
const databaseContent = await this.betterLocaleStorage.get(this.localStorageName())
|
|
25
25
|
|
|
26
26
|
this.connection = new SQL.Database(databaseContent)
|
|
27
|
+
await this.registerVersion()
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
localStorageName = () => `VelociousDatabaseDriversSqliteWeb---${digg(this.getArgs(), "name")}`
|
|
@@ -1,29 +1,4 @@
|
|
|
1
1
|
import InsertBase from "../../../query/insert-base.js"
|
|
2
2
|
|
|
3
3
|
export default class VelociousDatabaseConnectionDriversMysqlSqlInsert extends InsertBase {
|
|
4
|
-
toSql() {
|
|
5
|
-
let sql = `INSERT INTO ${this.getOptions().quoteTableName(this.tableName)} (`
|
|
6
|
-
let count = 0
|
|
7
|
-
|
|
8
|
-
for (let columnName in this.data) {
|
|
9
|
-
if (count > 0) sql += ", "
|
|
10
|
-
|
|
11
|
-
sql += this.getOptions().quoteColumnName(columnName)
|
|
12
|
-
count++
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
sql += ") VALUES ("
|
|
16
|
-
count = 0
|
|
17
|
-
|
|
18
|
-
for (let columnName in this.data) {
|
|
19
|
-
if (count > 0) sql += ", "
|
|
20
|
-
|
|
21
|
-
sql += this.getOptions().quote(this.data[columnName])
|
|
22
|
-
count++
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
sql += ")"
|
|
26
|
-
|
|
27
|
-
return sql
|
|
28
|
-
}
|
|
29
4
|
}
|
|
@@ -4,6 +4,7 @@ import * as inflection from "inflection"
|
|
|
4
4
|
import JoinPlain from "./join-plain.js"
|
|
5
5
|
import OrderPlain from "./order-plain.js"
|
|
6
6
|
import Preloader from "./preloader.js"
|
|
7
|
+
import RecordNotFoundError from "../record/record-not-found-error.js"
|
|
7
8
|
import SelectPlain from "./select-plain.js"
|
|
8
9
|
import WhereHash from "./where-hash.js"
|
|
9
10
|
import WherePlain from "./where-plain.js"
|
|
@@ -46,6 +47,21 @@ export default class VelociousDatabaseQuery {
|
|
|
46
47
|
|
|
47
48
|
getOptions = () => this.driver.options()
|
|
48
49
|
|
|
50
|
+
async find(recordId) {
|
|
51
|
+
const conditions = {}
|
|
52
|
+
|
|
53
|
+
conditions[this.modelClass.primaryKey()] = recordId
|
|
54
|
+
|
|
55
|
+
const query = this.clone().where(conditions)
|
|
56
|
+
const record = await query.first()
|
|
57
|
+
|
|
58
|
+
if (!record) {
|
|
59
|
+
throw new RecordNotFoundError(`Couldn't find ${this.modelClass.name} with '${this.modelClass.primaryKey()}'=${recordId}`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return record
|
|
63
|
+
}
|
|
64
|
+
|
|
49
65
|
async findBy(conditions) {
|
|
50
66
|
const newConditions = {}
|
|
51
67
|
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import restArgsError from "../../utils/rest-args-error.js"
|
|
2
|
+
|
|
1
3
|
export default class VelociousDatabaseQueryInsertBase {
|
|
2
|
-
constructor({driver, tableName,
|
|
4
|
+
constructor({columns, data, driver, multiple, tableName, rows, ...restArgs}) {
|
|
3
5
|
if (!driver) throw new Error("No driver given to insert base")
|
|
4
6
|
if (!tableName) throw new Error(`Invalid table name given to insert base: ${tableName}`)
|
|
5
|
-
if (!data) throw new Error("No data given to insert base")
|
|
6
7
|
|
|
8
|
+
restArgsError(restArgs)
|
|
9
|
+
|
|
10
|
+
this.columns = columns
|
|
7
11
|
this.data = data
|
|
8
12
|
this.driver = driver
|
|
13
|
+
this.multiple = multiple
|
|
14
|
+
this.rows = rows
|
|
9
15
|
this.tableName = tableName
|
|
10
16
|
}
|
|
11
17
|
|
|
@@ -14,6 +20,56 @@ export default class VelociousDatabaseQueryInsertBase {
|
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
toSql() {
|
|
17
|
-
|
|
23
|
+
let sql = `INSERT INTO ${this.getOptions().quoteTableName(this.tableName)} (`
|
|
24
|
+
let count = 0
|
|
25
|
+
let columns
|
|
26
|
+
|
|
27
|
+
if (this.columns && this.rows) {
|
|
28
|
+
columns = this.columns
|
|
29
|
+
} else if (this.data) {
|
|
30
|
+
columns = Object.keys(this.data)
|
|
31
|
+
} else {
|
|
32
|
+
throw new Error("Neither 'column' and 'rows' or data was given")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const columnName of columns) {
|
|
36
|
+
if (count > 0) sql += ", "
|
|
37
|
+
|
|
38
|
+
sql += this.getOptions().quoteColumnName(columnName)
|
|
39
|
+
count++
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
sql += ") VALUES "
|
|
43
|
+
|
|
44
|
+
if (this.columns && this.rows) {
|
|
45
|
+
let count = 0
|
|
46
|
+
|
|
47
|
+
for (const row of this.rows) {
|
|
48
|
+
if (count >= 1) sql += ", "
|
|
49
|
+
|
|
50
|
+
count++
|
|
51
|
+
sql += this._valuesSql(row)
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
sql += this._valuesSql(Object.values(this.data))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return sql
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_valuesSql(data) {
|
|
61
|
+
let count = 0
|
|
62
|
+
let sql = "("
|
|
63
|
+
|
|
64
|
+
for (const value of data) {
|
|
65
|
+
if (count > 0) sql += ", "
|
|
66
|
+
|
|
67
|
+
sql += this.getOptions().quote(value)
|
|
68
|
+
count++
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
sql += ")"
|
|
72
|
+
|
|
73
|
+
return sql
|
|
18
74
|
}
|
|
19
75
|
}
|
|
@@ -7,7 +7,6 @@ import HasManyRelationship from "./relationships/has-many.js"
|
|
|
7
7
|
import HasManyInstanceRelationship from "./instance-relationships/has-many.js"
|
|
8
8
|
import * as inflection from "inflection"
|
|
9
9
|
import Query from "../query/index.js"
|
|
10
|
-
import RecordNotFoundError from "./record-not-found-error.js"
|
|
11
10
|
|
|
12
11
|
export default class VelociousDatabaseRecord {
|
|
13
12
|
static _relationshipExists(relationshipName) {
|
|
@@ -19,6 +18,7 @@ export default class VelociousDatabaseRecord {
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
static _defineRelationship(relationshipName, data) {
|
|
21
|
+
if (!relationshipName) throw new Error(`Invalid relationship name given: ${relationshipName}`)
|
|
22
22
|
if (!this._relationships) this._relationships = {}
|
|
23
23
|
if (this._relationshipExists(relationshipName)) throw new Error(`Relationship ${relationshipName} already exists`)
|
|
24
24
|
|
|
@@ -124,21 +124,6 @@ export default class VelociousDatabaseRecord {
|
|
|
124
124
|
return record
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
static async find(recordId) {
|
|
128
|
-
const conditions = {}
|
|
129
|
-
|
|
130
|
-
conditions[this.primaryKey()] = recordId
|
|
131
|
-
|
|
132
|
-
const query = this.where(conditions)
|
|
133
|
-
const record = await query.first()
|
|
134
|
-
|
|
135
|
-
if (!record) {
|
|
136
|
-
throw new RecordNotFoundError(`Couldn't find ${this.name} with '${this.primaryKey()}'=${recordId}`)
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return record
|
|
140
|
-
}
|
|
141
|
-
|
|
142
127
|
static _getConfiguration() {
|
|
143
128
|
if (!this._configuration) {
|
|
144
129
|
this._configuration = Configuration.current()
|
|
@@ -210,7 +195,7 @@ export default class VelociousDatabaseRecord {
|
|
|
210
195
|
this.prototype[name] = function () {
|
|
211
196
|
const locale = this._getConfiguration().getLocale()
|
|
212
197
|
|
|
213
|
-
return this.
|
|
198
|
+
return this._getTranslatedAttributeWithFallback(name, locale)
|
|
214
199
|
}
|
|
215
200
|
|
|
216
201
|
this.prototype[setterMethodName] = function (newValue) {
|
|
@@ -275,6 +260,10 @@ export default class VelociousDatabaseRecord {
|
|
|
275
260
|
return this._table
|
|
276
261
|
}
|
|
277
262
|
|
|
263
|
+
static async insertMultiple(columns, rows) {
|
|
264
|
+
return await this.connection().insertMultiple(this.tableName(), columns, rows)
|
|
265
|
+
}
|
|
266
|
+
|
|
278
267
|
static async last() {
|
|
279
268
|
const query = this._newQuery().order(this.primaryKey())
|
|
280
269
|
const record = await query.last()
|
|
@@ -414,10 +403,31 @@ export default class VelociousDatabaseRecord {
|
|
|
414
403
|
}
|
|
415
404
|
}
|
|
416
405
|
|
|
406
|
+
_getTranslatedAttributeWithFallback(name, locale) {
|
|
407
|
+
let localesInOrder
|
|
408
|
+
const fallbacks = this._getConfiguration().getLocaleFallbacks()
|
|
409
|
+
|
|
410
|
+
if (fallbacks && locale in fallbacks) {
|
|
411
|
+
localesInOrder = fallbacks[locale]
|
|
412
|
+
} else {
|
|
413
|
+
localesInOrder = [locale]
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
for (const fallbackLocale of localesInOrder) {
|
|
417
|
+
const result = this._getTranslatedAttribute(name, fallbackLocale)
|
|
418
|
+
|
|
419
|
+
if (result && result.trim() != "") {
|
|
420
|
+
return result
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
417
425
|
_setTranslatedAttribute(name, locale, newValue) {
|
|
418
|
-
let translation = this.translations().loaded()?.find((translation) =>translation.locale() == locale)
|
|
426
|
+
let translation = this.translations().loaded()?.find((translation) => translation.locale() == locale)
|
|
419
427
|
|
|
420
|
-
if (!translation)
|
|
428
|
+
if (!translation) {
|
|
429
|
+
translation = this.translations().build({locale})
|
|
430
|
+
}
|
|
421
431
|
|
|
422
432
|
const assignments = {}
|
|
423
433
|
|
|
@@ -447,6 +457,10 @@ export default class VelociousDatabaseRecord {
|
|
|
447
457
|
return this._newQuery()
|
|
448
458
|
}
|
|
449
459
|
|
|
460
|
+
static async find(...args) {
|
|
461
|
+
return this._newQuery().find(...args)
|
|
462
|
+
}
|
|
463
|
+
|
|
450
464
|
static async findBy(...args) {
|
|
451
465
|
return this._newQuery().findBy(...args)
|
|
452
466
|
}
|
|
@@ -519,7 +533,7 @@ export default class VelociousDatabaseRecord {
|
|
|
519
533
|
_hasChanges = () => Object.keys(this._changes).length > 0
|
|
520
534
|
|
|
521
535
|
isChanged() {
|
|
522
|
-
if (this.isNewRecord() || this._hasChanges())
|
|
536
|
+
if (this.isNewRecord() || this._hasChanges()){
|
|
523
537
|
return true
|
|
524
538
|
}
|
|
525
539
|
|
|
@@ -543,6 +557,18 @@ export default class VelociousDatabaseRecord {
|
|
|
543
557
|
return false
|
|
544
558
|
}
|
|
545
559
|
|
|
560
|
+
changes() {
|
|
561
|
+
const changes = {}
|
|
562
|
+
|
|
563
|
+
for (const changeKey in this._changes) {
|
|
564
|
+
const changeValue = this._changes[changeKey]
|
|
565
|
+
|
|
566
|
+
changes[changeKey] = [this._attributes[changeKey], changeValue]
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return changes
|
|
570
|
+
}
|
|
571
|
+
|
|
546
572
|
_tableName() {
|
|
547
573
|
if (this.__tableName) return this.__tableName
|
|
548
574
|
|