AbstractBone

AbstractBone

Shared model implementation for Leoric records.

Applications normally extend Bone; this class documents the model metadata, persistence, association, and schema APIs inherited by Bone.

Constructor

new AbstractBone()

Members

(static) all

SELECT all rows. In production, when the table is at large, it is not recommended to access records in this way. To iterate over all records, Bone.batch shall be considered as the better alternative. For tables with soft delete enabled, which means they've got deletedAt attribute, use Bone.unscoped to discard the default scope.

(static) columnAttributes

get attributes except virtuals

(static) first

SELECT rows ORDER BY primary key ASC LIMIT 1

(static) last

SELECT rows ORDER BY primary key DESC LIMIT 1

(static) pool

get the connection pool of the driver

(static) primaryColumn

The primary column of the table, defaults to id. This is Bone.primaryKey in snake case.

(static) primaryKey

The primary key of the model, defaults to id.

Methods

_clone()

Protected clone — replaces internal state with merged data from target. Note: this here is the proxy (all method calls go through proxy). The proxy has no set trap, so Symbol-key assignments delegate to the underlying target.

_create()

Internal create implementation

(async) _save()

Internal save dispatcher deciding between create/update/upsert

_upsert()

Internal upsert implementation

_validateAttributes()

Instance attribute validation

attribute(name, value)

Get or set an attribute value. As a getter, returns the current value (undefined when not loaded); as a setter, casts and stores the value and returns the instance for chaining.

Parameters:
Name Type Description
name

attribute name

value

value to set

Returns:

the current attribute value, or the instance itself when called as a setter

Example:
bone.attribute('foo');     // => 1
bone.attribute('foo', 2);  // => bone

attributeChanged()

See if attribute has been changed or not.

Deprecated:
  • Bone#changed is preferred
Example:
bone.attributeChanged('foo')

attributeWas()

Get the original attribute value.

Example:
bone.attributeWas('foo')  // => 1

changes(name)

Get attribute changes as { [name]: [valueWas, value] } pairs since the record was loaded or last saved.

Parameters:
Name Type Description
name

attribute name; when provided, only the change of that attribute is returned

Example:
post.title = 'New';
post.changes();   // => { title: ['Old', 'New'] }

create(opts)

INSERT the current record into the database, syncing generated timestamps and primary key. Resolves to the instance itself.

Parameters:
Name Type Description
opts

query options; set hooks to false to skip hooks

Example:
const post = new Post({ title: 'Leoric' });
await post.create();

getRaw(key)

Get the raw attribute values as stored internally, bypassing custom getters. With a name, only the raw value of that attribute is returned.

Parameters:
Name Type Description
key

attribute name

Example:
post.getRaw();          // => { id: 1, title: 'Leoric' }
post.getRaw('title');   // => 'Leoric'

getRawPrevious(key)

Get the raw attribute values as persisted by the save before last, bypassing custom getters. With a name, only the raw value of that attribute is returned.

Parameters:
Name Type Description
key

attribute name

getRawSaved(key)

Get the raw attribute values as persisted by the last save, bypassing custom getters. With a name, only the raw value of that attribute is returned.

Parameters:
Name Type Description
key

attribute name

hasAttribute(name)

Check whether the model has an attribute with the given name.

Parameters:
Name Type Description
name

attribute name

Returns:

true when the attribute exists

(async) jsonMergePreserve()

UPDATE JSONB column with JSON_MERGE_PRESERVE function

Example:
/// before: bone.extra equals { name: 'zhangsan', url: 'https://alibaba.com' }
bone.jsonMergePreserve('extra', { url: 'https://taobao.com' })
/// after: bone.extra equals { name: 'zhangsan', url: ['https://alibaba.com', 'https://taobao.com'] }

previousChanged(name)

See if attribute was changed previously or not, compared against the state before the most recent save.

Parameters:
Name Type Description
name

attribute name; when provided, only that attribute is checked

Example:
post.previousChanged('title')

previousChanges(name)

Get attribute changes as { [name]: [valueWas, value] } pairs compared against the state before the most recent save, one save further back than changes().

Parameters:
Name Type Description
name

attribute name; when provided, only the change of that attribute is returned

Example:
post.previousChanges();   // => { title: ['Old', 'New'] }

(async) reload()

Reload the record from the database, discarding any unpersisted changes. Resolves to the freshly fetched instance when found.

Example:
await post.reload();

(async) remove()

Remove current record. If deletedAt attribute exists, then instead of DELETing records from database directly, the records will have their deletedAt attribute UPDATEd instead. To force DELETE, no matter the existence of deletedAt attribute, pass true as the argument.

Example:
bone.remove()      // => UPDATE ... SET deleted_at = now() WHERE ...
bone.remove(true)  // => DELETE FROM ... WHERE ...
bone.remove(true, { hooks: false })

(async) restore(opts)

Restore a soft-deleted record by clearing its deletedAt attribute. Only works for paranoid models with a deletedAt attribute, otherwise an Error is thrown.

Parameters:
Name Type Description
opts

query options

Example:
await post.remove();
await post.restore();

save()

Persist changes of current record to database. If current record has never been saved before, an INSERT query is performed. If the primary key was set and is not changed since, an UPDATE query is performed. If the primary key is changed, an INSERT ... UPDATE query is performed instead.

If affectedRows is needed, consider using the corresponding methods directly.

Example:
new Bone({ foo: 1 }).save()                   // => INSERT
new Bone({ foo: 1, id: 1 }).save()            // => INSERT ... UPDATE
(await Bone.first).attribute('foo', 2).save()  // => UPDATE
new Bone({ foo: 1, id: 1 }).save({ hooks: false })            // => INSERT ... UPDATE

syncRaw()

Sync raw caches after persistence

toObject() → {Object}

Generate a plain object of the instance, similar to Bone#toJSON, except that nested records are converted through their own toObject(). Bone#toObject might be called on descents of Bone that does not have attributes defined on them directly, hence for..in is preferred.

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
Returns:
Type:
Object
Example:
const post = await Post.first
post.toObject()  // => { id: 1, ... }

upsert(opts)

update or insert record.

Parameters:
Name Type Description
opts

queryOptions

Example:
bone.upsert() // INSERT ... VALUES ON DUPLICATE KEY UPDATE ...
bone.upsert({ hooks: false })

validate()

Validate current attribute changes. Throws LeoricValidateError when any value fails validation.

Example:
post.validate();

(static) _find()

Internal finder powering all query starts.

(static) _getColumns(data)

get actual update/insert columns to avoid empty insert or update

Parameters:
Name Type Description
data

(static) _remove()

private method for internal calling Remove any record that matches conditions.

  • If forceDelete is true, DELETE records from database permanently.
  • If not, update deletedAt attribute with current date.
  • If forceDelete isn't true and there is no deletedAt attribute, records are hard-deleted.
Example:
Post.remove({ title: 'Leah' })         // mark Post { title: 'Leah' } as deleted
Post.remove({ title: 'Leah' }, true)   // delete Post { title: 'Leah' }
Post.remove({}, true)                  // delete all data of posts

(static) _restore()

Restore soft-deleted rows by clearing deletedAt.

Example:
Bone.restore({ title: 'aaa' })
Bone.restore({ title: 'aaa' }, { hooks: false })

(static) _update()

Update any record that matches conditions.

(static) _validateAttributes()

Static attribute validation

(static) associate()

Mount association metadata, verifying existence and applying paranoid defaults.

(static) attribute()

Override attribute metadata

Example:
Bone.attribute('foo', { type: JSON })

(static) belongsTo(name, options)

Define a belongsTo association. The foreign key defaults to <associatedModelName>Id on this model.

Parameters:
Name Type Description
name

association name, e.g. 'user'

options

association options including className and foreignKey

Example:
Post.belongsTo('user');

(async, static) bulkCreate()

Batch INSERT

(static) create()

INSERT rows

Example:
Bone.create({ foo: 1, bar: 'baz' })

(async, static) describe()

Fetch the schema information of the model's table, keyed by column name.

Example:
await Post.describe();

(async, static) drop()

DROP the table

(static) get()

SELECT rows OFFSET index LIMIT 1

Example:
Bone.get(8)
Bone.find({ foo: { $gt: 1 } }).get(42)

(static) group()

Set GROUP fields

Example:
Bone.group('foo')
Bone.group('MONTH(createdAt)')

(static) hasAttribute(name)

Model.hasAttribute(name)

Parameters:
Name Type Description
name

(static) hasMany(name, options)

Define a hasMany association. The foreign key defaults to <thisModelName>Id on the associated model.

Parameters:
Name Type Description
name

association name, e.g. 'posts'

options

association options including className, foreignKey, and through

Example:
User.hasMany('posts');

(static) hasOne(name, options)

Define a hasOne association. The foreign key defaults to <thisModelName>Id on the associated model.

Parameters:
Name Type Description
name

association name, e.g. 'profile'

options

association options including className, foreignKey, and through

Example:
User.hasOne('profile');

(static) include()

Short of Bone.find().with(...names)

Example:
Post.include('author', 'comments').where('posts.id = ?', 1)

(static) init(attributes, opts, overrides)

Initialize the model with attribute definitions, table name, timestamps, hooks, and custom property descriptors. Usually invoked through realm.define() or the @Model() decorator.

Parameters:
Name Type Description
attributes

attribute definitions keyed by attribute name

opts

model options including tableName, timestamps, underscored, and hooks

overrides

custom property descriptors installed on the prototype

Example:
Post.init({ title: DataTypes.STRING }, { tableName: 'posts' });

(static) initialize()

Apply association metadata registered via decorators (@HasOne, @HasMany, @BelongsTo) onto the model. Called by the realm after the model is loaded.

(static) join()

JOIN arbitrary models with given ON conditions

Example:
Bone.join(Muscle, 'bones.id == muscles.boneId')

(static) joinMany(…args)

JOIN arbitrary models with given ON conditions and mount all matching rows as a collection.

Parameters:
Name Type Attributes Description
args <repeatable>

The model, ON conditions, and optional bound values.

Returns:

A chainable query that mounts all matching rows.

Example:
Bone.joinMany(Muscle, 'bones.id == muscles.boneId')

(static) jsonMerge()

JSON merge convenience for update

(static) loadAttribute()

Load attribute definition to merge default getter/setter and custom descriptor on prototype

(static) order()

Set ORDER fields

Example:
Bone.order('foo')
Bone.order('foo', 'desc')
Bone.order({ foo: 'desc' })

(async, static) query()

Execute a raw query

Example:
Bone.query('SELECT * FROM posts WHERE id = ?', [1])
Bone.query('SELECT * FROM posts WHERE id = :id', { replacements: { id: 1 } })

(static) remove()

Remove rows. If soft delete is applied, an UPDATE query is performed instead of DELETing records directly. Set forceDelete to true to force a DELETE query.

(static) renameAttribute()

Rename attribute

Example:
Bone.renameAttribute('foo', 'bar')

(static) select()

Whitelist SELECT fields by names or filter function

Example:
Bone.select('foo')
Bone.select('foo, bar')
Bone.select('foo', 'bar')
Bone.select('MONTH(date), foo + 1')
Bone.select(name => name !== foo)

(async, static) sync(options)

Synchronize the model's table with its attribute definitions. The table is created when it does not exist; with force: true it is dropped and recreated (existing data is destroyed), with alter: true it is altered in place, otherwise a warning is printed when out of sync.

Parameters:
Name Type Description
options

synchronization options force and alter

Example:
await Post.sync({ force: true });

(async, static) transaction()

Grabs a connection and starts a transaction process. Both GeneratorFunction and AsyncFunction are acceptable. If GeneratorFunction is used, the connection of the transaction process will be passed around automatically.

Example:
Bone.transaction(function* () {
  const bone = yield Bone.create({ foo: 1 })
  yield Muscle.create({ boneId: bone.id, bar: 1 })
});

(async, static) truncate()

TRUNCATE table to clear records.

(static) unalias(name)

Convert an attribute name to its underlying column name. Names that are not attributes are returned unchanged.

Parameters:
Name Type Description
name

attribute name

Example:
Post.unalias('createdAt');   // => 'created_at'

(static) upsert(values, opt)

INSERT or UPDATE rows

Parameters:
Name Type Description
values

values

opt

query options

Example:
Bone.upsert(values, { hooks: false })

(static) where()

Set WHERE conditions

Example:
Bone.where('foo = ?', 1)
Bone.where({ foo: { $eq: 1 } })