-
Notifications
You must be signed in to change notification settings - Fork 0
Model
class Model 📜
The base Model class for Mythix ORM. Every Mythix ORM model should inherit from this class. This class provides support for all model operations in Mythix ORM.
Notes:
- Many model methods have both static and instance
methods of the same name that do the same thing.
This is because it is common to access Model
methods directly on the model class as well as an
instance. For example, Model.static getModelName is both
a static method, and an instance method. Nearly all
the methods listed here have both a
staticand and instance version. We are only listing thestaticversions because the instance versions generally will just be proxies to thesestaticmethods. - An underscore prefix on a method in Mythix ORM implies that this method should not be overloaded unless you know exactly what you are doing. It also implies that there is another method that can and should be overloaded instead.
static property Model::_isMythixModel: boolean 📜
This property assists with type checking.
This casts a field value to its type,
by calling the field's field.type.castValue
method for the type.
Arguments:
field: FieldThe field to use to cast the value. The
typeproperty on the field will be accessed, and thetypepropertiescastValuemethod will be called on the providedvalueargument.value:anyThe value to cast to the field's type.
nullis a valid value, and allcastValuemethods on types should properly handle it.Return value:
anyThe value provided, cast to the type of the field.
method Model::_constructField(fieldName, field) 📜
This method simply creates the getters/setters for fields as described by Model._constructFields.
Arguments:
fieldNamefield
method Model::_constructFields() 📜
Construct the model's fields on the model instance.
This method will iterate the static Model.fields
fields for the model. For each field (except virtual
fields), it will call field.type.exposeToModel().
If this method returns true, then the field will
be added as a getter/setter to the model instance,
with the name defined as the field's fieldName.
For example, if a User model had a field named
fieldName: 'firstName', then the firstName
property will be added to the model instance, as a
getter/setter property on the instance. The getter/
setter provide the functionality of sending data in
and out of get and set methods on the field itself,
and through each field.type.castValue method on set.
The setter will also mark a field as dirty if it is set
to a value that is different from the current value of
the field. The Model.getDataValue and
Model.setDataValue instance methods will bypass
the getter/setter of each field, allowing direct access
to the underlying attribute value.
method Model::_constructor(data?: object): undefined 📜
This is the final call the constructor makes
before it finalizes instantiating the model.
It calls Model._constructFields to
construct the model's fields, and then it calls
Model._initializeModelData to initialize
the field values for the model.
Arguments:
data?:objectAttributes provided to the model through the
constructorcall.Return value:
undefined
method Model::_getConnection(connection?: Connection): Connection 📜
See Model.static _getConnection
Notes:
- Pay attention that unlike Model.static _getConnection this checks the model's instance for
._connectionproperty. If that is a valid connection, then it will be returned before the bound connection. This is helpful when you have chosen not to bind a connection to your models. This will allow you to provide a connection directly when you create the model, which can make interacting with the model less tiresome. i.e.new Model(null, { connection }).Arguments:
connection?: ConnectionAn optional connection that can be provided. If provided, it will simply be returned. Otherwise, if not provided, or a falsy value, then attempt to fallback to
modelInstance._connection, if that also fails to find a connection, the finally the method will call Model.static _getConnection to get the bound connection, if any is available.Return value: Connection
method Model::_getDirtyFields(options?: DirtyFieldOptions): DirtyFieldChangeList 📜
Get the dirty fields of the model instance.
The model instance property Model.changes
calls this method to get the list of dirty
fields for the model instance. Unlike
Model.changes, which is a getter, you can
pass options to this method, which can change
its behavior.
If this method is provided a Connection via the
connection options value, then it will assume it is being
used in a connection method to fetch the dirty fields for
a database operation (update, or insert). If it has a
Connection then it will behave a little differently.
The first difference is that if a model field is not marked
as dirty, then it will be passed through Connection.dirtyFieldHelper.
If this method returns any value other than undefined, then
that value will be used as the "dirty" value for the field, and
the field will be marked as dirty. This can be used when you
want the connection itself to control the dirty state of a field.
This is what is done with SQLite BigInt AUTOINCREMENT emulation.
Any time an autoincrementing BigInt is being stored to a SQLite
database with the emulateBigIntAutoIncrement option enabled,
an internal counter for this field is incremented, and the field
is automatically updated as "dirty" (on insert only, if the field
has and undefined value).
The next difference when using a connection in this method is
that it will check if this is an "update" or an "insert" operation
by checking the update and insert "option" keys respectively.
If one of these is true, then it will invoke defaultValue property
on the field, if said defaultValue has the onUpdate, or onInsert
flags set to true. This can be used for example on created_at,
and updated_at fields, which will only be marked dirty and given
a value on an insert or update operation through the connection.
Without a connection provided to this method, it will simply
return the "change list" of all dirty fields on the model. The
"change list" is an object, where each key is the name of the field,
and each value is another object, with previous and current keys
describe the change that took place to the field. For example:
DirtyFieldChangeList = {
firstName: {
previous: undefined,
current: 'Bob',
},
}If no fields on the model are dirty, then an empty object will be returned. A field is considered "dirty" if its value is different from what it was when the model was first instantiated, or since the last time the Model.clearDirty method was called.
The options argument has the
following shape:
Interface:
interface DirtyFieldOptions { connection: Connection; // The connection for this operation. update: boolean; // If `true`, then this is an update operation. insert: boolean; // If `true`, then this is an insert operation. // ... any options you wish to pass to `connection.dirtyFieldHelper` }Notes:
- If this is an "update" or "insert" operation, as defined by the
updateorinsert"options", then the default value for the field will be fetched via the QueryGenerator.getFieldDefaultValue method through the providedconnection.Arguments:
options?:DirtyFieldOptionsOptions to provide to the method.
Return value:
DirtyFieldChangeList
Get a field's value. Calling this is no different
from accessing the field directly on the model instance
itself. For example, userInstance.firstName is identical
to calling userInstance._getFieldValue('firstName', User.fields.firstName).
This will call the get method defined on the field, if any is defined.
If a get method is defined, then whatever value it returns will be
the result of this method. If no get method is defined on the field,
then this.getDataValue(fieldName) is called instead, and will provide
the resulting return value for this method.
Notes:
- Never call this method (or the model attribute by name), while inside a field's
getmethod. If you do, you will enter an infinite recursive loop. Instead, call the providedgetmethod (as provided by the context), or call Model.getDataValue.Arguments:
fieldName:stringThe name of the field whose value we wish to get.
field: FieldThe field definition itself for the value we wish to get.
Return value:
anySee also: Field
method Model::_initializeFieldData(fieldName: string, field: Field, fieldValue: any, data: object) 📜
Set each field's initial value. Each field's value
will first be fetched from the data argument
given to the constructor--if any was given. After
all field attributes have been set this way, then
this method is called, being provided that value (if
any) via the fieldValue argument. If fieldValue
is undefined, then call the defaultValue property
of the field to get the field's initial value.
Arguments:
fieldName:stringThe name of the field we are initializing.
field: FieldThe field definition itself for the field we are initializing.
fieldValue:anyThe field value as provided by the
dataargument to the modelconstructor, if any was provided.data:objectThe
dataargument, as provided to theconstructorof the model.
method Model::_initializeModelData(data?: object) 📜
Initialize the field value for each field/attribute.
If no data argument is passed to the constructor,
then each field will be initialized to its default
value, as defined by the defaultValue property on
each field. A null value is a valid value, and
though it will still be piped through each field's
field.type.castValue method, it will discount the
need to call defaultValue on the field.
This method calls Model._initializeFieldData
to actually set the value of each field. Field values
are set from the provided data object to the constructor
first, for all fields, before any defaultValue calls
for any fields are attempted.
Notes:
- All fields have already been constructed before this method is called via Model._constructFields.
- Virtual fields are not constructed against the model instance, however, field types can modify the instance, and some do. For example, the
Types.ModelandTypes.Modelsvirtual field types inject relational methods on the model.- Only concrete fields are considered "attributes" of the model, and can have an initial value provided via the
dataargument to the constructor, or via adefaultValueproperty on the field.Arguments:
data?:objectAttributes values for fields. Can be nothing, in which case the
defaultValueproperty for each field will be used instead.nullis a valid value, and if an attribute has anullvalue, it will not be given a default value fromdefaultValue.
Set a field's value. Calling this is no different
from setting the field directly on the model instance
itself. For example, userInstance.firstName = 'Bob' is identical
to calling userInstance._setFieldValue('firstName', User.fields.firstName, 'Bob').
This will call the set method defined on the field, if any is defined.
If a set method is defined, then it is entirely up to the set method
to call this.setDataValue to set the field's value.
If no set method is defined on the field, then this.setDataValue(fieldName, value)
is called instead, and will set the value on the field.
Notes:
- This method will mark the field as dirty if the value provided differs from the current value the field has.
- Never call this method (or set the model attribute by name), while inside a field's
setmethod. If you do, you will enter an infinite recursive loop. Instead, call the providedsetmethod (as provided by the context), or call Model.setDataValue.Arguments:
fieldName:stringThe name of the field whose value we wish to get.
field: FieldThe field definition itself for the value we wish to get.
Return value:
undefinedSee also: Field
method Model::clearDirty(fieldName?: string): boolean 📜
Clear the dirty state of the model, or of a single field.
If a fieldName argument is provided, then only the specified
field's "dirty" status will be cleared. If no fieldName
argument is provided, then all field's on the model will have
their "dirty" status cleared, and the model will no longer be
"dirty".
The "dirty" status of a field is cleared by 1) setting the real
underlying field value (this._fieldData) to the dirty field value,
and 2) removing the entry in this._dirtyFieldData on the model for
the field.
Arguments:
fieldName?:stringIf specified, clear only this field's "dirty" status. If not specified, clear all fields on the model, making the entire model no longer dirty.
Return value:
boolean
Construct a new Model instance.
Arguments:
data?:objectAttributes to provide to the new model instance. The key names should be a
fieldName, not acolumnName. Any model attribute missing fromdata, or whose value isundefined, will be given a default value from thedefaultValue, field property for the field. If thedefaultValuefor the field is marked as a "remote" value (a value provided by the database) or ifdefaultValueis not marked with the flagFLAG_ON_INITIALIZE, then the field will remain with a value ofundefined, at least until the model is stored to the database. The default for all methods provided to thedefaultValuekey of the field is to have theFLAG_ON_INITIALIZEflag, so the value will be created on model instantiation. Some default value methods however, such asAUTOINCREMENT, do not have theFLAG_ON_INITIALIZEset, because the defaultValue is provided by the database.nullis a valid value, and if provided for an attribute, then thedefaultValuewill not be used. Any attribute value provided will go throughfield.type.castValuefrom the fieldtypeproperty (this includesnullvalues). Any attributes provided will immediately be marked as "dirty" as soon as the model is instantiated.options?:objectOptions for the model. The only property Mythix ORM will use is the
connectionkey. If provided, it will set this as the_connectionproperty on the instance. Otherwise, these options are intended to be used by you, the developer, to do with as you please on your models. They can be fetched from any model instance simply by calling Model.getOptions.Return value: Model
method Model::destroy(options?: object): number 📜
Destroy this model instance.
Calling this method will destroy this model from the database.
If the model is not persisted, then nothing will happen, and
0 will be returned. If the model is persisted, the result
of Connection.destroy is returned, which is the number
of rows modified in the database, which in this case should always
be 1.
If the model has no primary key field defined, then an exception will be thrown.
Notes:
- A primary key is required on the model for this method to work. If you don't have a primary key defined, then you will need to create your own "destroy" operation.
Arguments:
options?:objectOptions to pass to the underlying QueryEngine.destroy call. If a
connectionproperty is present on this options object, then it will be used as the connection for this operation.Return value:
numberThe number of rows modified in the database.
method Model::getAttributes(): object 📜
Get all the models current raw attributes.
This will return an object, where each key
is the fieldName of each non-virtual (concrete)
field on the model, and each value is the "current"
value of the field on the model. The "current"
value for each field could either be a dirty field
value, or a clean (or raw) field value.
This method is nearly identical to Model.toJSON
except that Model.toJSON always adds the primary
key to the result first, which only matters for JavaScript
engines that honor the insertion order of keys in native
Objects, which is never guaranteed. Model.toJSON
also differs from this method by calling field.type.serialize
for every attribute on the model.
Notes:
- Field's with
undefinedvalues will not be included in the resulting object.Return value:
objectAll models attributes (field values).
method Model::getConnection(connection?: Connection): Connection 📜
Get the underlying connection bound to the model's class. Connection binding is optional, so this method can also be provided a connection. If a connection is provided, then it will simply be returned. Because Mythix ORM has no globals, this is a design pattern to supply a connection if you have one available, or fallback to a "bound" connection (if one can be found). This method should be overloaded if you wish to provide your own model specific connection.
This method will also search for a modelInstance.connection,
and return that connection if found.
Notes:
static getConnectionis simply a proxy forstatic _getConnection, whereas this instance method will also attempt to find a connection on the model instance itself.Arguments:
connection?: ConnectionAn optional connection that can be provided. If provided, it will simply be returned. Otherwise, if not provided, or a falsy value, then attempt to fallback to the bound connection, if any is available.
Return value: Connection
method Model::getDataValue(fieldName: string): any 📜
Get the current value of any field on the model. The "current" value will be the dirty value if the field is dirty, or it will be the clean value of the field if the field isn't dirty.
This method is a "raw" get of the field's value
in that it won't call get on the field descriptor,
if any is defined. Instead it will first attempt to
fetch the current value of the field from this._dirtyFieldData,
if there is an entry for the field in the this._dirtyFieldData
property of the model instance. If there is no "dirty" entry for
the field, then its "clean value" (or raw value) will be fetched
from the underlying this._fieldData storage area for field values.
Arguments:
fieldName:stringThe name of the field whose value you wish to fetch.
Return value:
any
Get the dirty field descriptors themselves for all fields that are dirty.
Whereas Model._getDirtyFields returns a "change list" of dirty fields, this method will return the field descriptors themselves. An array of Field will be returned for each dirty field, or an empty array if no fields are dirty.
Arguments:
options?:objectIf provided, this will be the "options" supplied to Model._getDirtyFields.
Return value: Array<Field>
The dirty fields of the model.
method Model::getOptions(): object 📜
Get the options provided to the model, if any. This will always return an object, even if no options were provided, in which case the object will simply be an empty object.
Return value:
objectOptions object provided by the user to the model when the model was constructed.
method Model::hasValidPrimaryKey(): boolean 📜
Checks if the primary key's value is valid.
Validity checks are handled by the field's type.
When this method is called, the primary key
field for the model is fetched, and if found,
the field.type.isValidValue method will be called
and provided with the current value of the
primary key field.
Type.isValidValue
is commonly implemented to be a strict check
against the type. null will generally
return false for an isValidValue call, however
implementation details are entirely left up to
the isValidValue method defined on the type.
Return value:
boolean
method Model::isDirty(fieldName?: string): boolean 📜
Check if the model is dirty or not.
If a fieldName is provided as an argument,
it will only check if the specified field
is dirty or not. If not provided, then the
entire model will be considered "dirty" if
one or more fields are marked as "dirty".
Arguments:
fieldName?:stringIf provided, check if this one field is dirty. If not provided, then check if any field on the model is dirty.
Return value:
boolean
method Model::isPersisted(): boolean 📜
Check if the model is persisted or not.
This has nothing to do with the model's "dirty" state.
if the model is dirty, then this will still report
true if the model was initially loaded from the database.
Return value:
boolean
trueif the model was loaded from the database,falseotherwise.
method Model::onAfterCreate(context: object) 📜
After insert model hook.
This method will be called on each model instance after it has been inserted into the database. This method is called after each model instance has been fully stored, marked as persisted, and marked as not dirty. If you set any model fields in this method, then the model will be marked as dirty, and will be re-saved at the end of the insert operation.
Notes:
- Use care when updating model attributes in this method. At the end of each insert operation, the models just stored are scanned to see if any of them are dirty. If they are dirty they will be re-stored to the database using an update operation. This can happen for example if foreign keys are in use. We might not be able to update a foreign key field value until after the insert operation is completed. When a foreign key value is updated post-insert, then the model might again become dirty, and be updated post-insert. Because of this, you should be careful about making your model dirty in any "after" hooks, as you might unintentionally incur the cost of a post-insert update.
Arguments:
context:objectA context object that is provided to all model hooks. The shape of this object is
{ connection, Model, options }. It will contain the currentconnectionfor the operation (which might be a transaction connection), theModelfor the operation, which is the "root model" of the operation, not necessarily "this" model (the model whose hook is being called), and the "options" defined for the current operation.
method Model::onAfterSave(context: object) 📜
After insert or update model hook.
This method will be called on each model instance after it has been inserted or updated in the database. This method is called after each model instance has been fully stored, marked as persisted, and marked as not dirty. If this is an insert operation, and if you set any model fields in this method, then the model will be marked as dirty, and will be re-saved at the end of the insert operation.
Notes:
- Use care when updating model attributes in this method. At the end of each insert operation, the models just stored are scanned to see if any of them are dirty. If they are dirty they will be re-stored to the database using an update operation. This can happen for example if foreign keys are in use. We might not be able to update a foreign key field value until after the insert operation is completed. When a foreign key value is updated post-insert, then the model might again become dirty, and be updated post-insert. Because of this, you should be careful about making your model dirty in any "after" hooks, as you might unintentionally incur the cost of a post-insert update.
Arguments:
context:objectA context object that is provided to all model hooks. The shape of this object is
{ connection, Model, options }. It will contain the currentconnectionfor the operation (which might be a transaction connection), theModelfor the operation, which is the "root model" of the operation, not necessarily "this" model (the model whose hook is being called), and the "options" defined for the current operation.
method Model::onAfterUpdate(context: object) 📜
After update model hook.
This method will be called on each model instance after it has been update in the database. This method is called after each model instance has been fully stored, marked as persisted, and marked as not dirty. Unlike an insert operation, update operations do not have a post-operation dirty model scan and re-update. You can safely update model attributes in this method without the worry of incurring the cost of an extra store operation. However, if you do set model attributes in this method, then the model will be marked dirty when the update operation is complete.
Arguments:
context:objectA context object that is provided to all model hooks. The shape of this object is
{ connection, Model, options }. It will contain the currentconnectionfor the operation (which might be a transaction connection), theModelfor the operation, which is the "root model" of the operation, not necessarily "this" model (the model whose hook is being called), and the "options" defined for the current operation.
method Model::onBeforeCreate(context: object) 📜
Before insert model hook.
This method will be called on each model instance before it is inserted into the database. This method is called before dirty fields are calculated for the insert operation, so you can set field values here before insert, and they will be captured and inserted into the database.
Arguments:
context:objectA context object that is provided to all model hooks. The shape of this object is
{ connection, Model, options }. It will contain the currentconnectionfor the operation (which might be a transaction connection), theModelfor the operation, which is the "root model" of the operation, not necessarily "this" model (the model whose hook is being called), and the "options" defined for the current operation.
method Model::onBeforeSave(context: object) 📜
Before save model hook.
This method will be called on each model instance before it is inserted or updated in the database. This method is called before dirty fields are calculated for the insert or update operation, so you can set field values here before update, and they will be captured and updated in the database.
Notes:
- This is the final hook call before the insert or update operation sends your data off to the database.
Arguments:
context:objectA context object that is provided to all model hooks. The shape of this object is
{ connection, Model, options }. It will contain the currentconnectionfor the operation (which might be a transaction connection), theModelfor the operation, which is the "root model" of the operation, not necessarily "this" model (the model whose hook is being called), and the "options" defined for the current operation.
method Model::onBeforeUpdate(context: object) 📜
Before update model hook.
This method will be called on each model instance before it is updated in the database. This method is called before dirty fields are calculated for the update operation, so you can set field values here before update, and they will be captured and updated in the database.
Arguments:
context:objectA context object that is provided to all model hooks. The shape of this object is
{ connection, Model, options }. It will contain the currentconnectionfor the operation (which might be a transaction connection), theModelfor the operation, which is the "root model" of the operation, not necessarily "this" model (the model whose hook is being called), and the "options" defined for the current operation.
method Model::onValidate(context: object): Array<any> 📜
Validate all concrete fields on the model.
This method is called before any "insert"
or "update" operation happens for the model.
It will iterate all the fields of the model,
and call the validate method defined on
each field descriptor (Field),
if any is defined.
Each validate method is asynchronous, so
all promises will be collected from all validate
method calls, and will be awaited upon via
await Promise.all(validatePromises);.
Model validation will fail if any validate
method throws an exception.
onValidate is called directly from Model.onBeforeSave,
so make certain you call super.onBeforeSave(...args) if you
overload onBeforeSave. If you don't, your validation hooks
won't be called. This design was deliberate, so the developer
could choose to bypass model validation on purpose simply
by not calling super.onBeforeSave(...args) should they choose not to.
Feel free to overload onValidate to provide your own implementation.
Notes:
validateproperties on fields must always be methods. Unlike other ORMs, we don't allow a pattern, a RegExp, or anything else. You must provide the implementation of eachvalidatemethod directly yourself (which could for example use a RegExp to check the field's value).Arguments:
context:objectA context object that is provided to all model hooks. The shape of this object is
{ connection, Model, options }. It will contain the currentconnectionfor the operation (which might be a transaction connection), theModelfor the operation, which is the "root model" of the operation, not necessarily "this" model (the model whose hook is being called), and the "options" defined for the current operation.Return value:
Array<any>Results of each
validatecall from each field. Will generally beundefinedfor each call. The validation for a field will only fail if an exception is thrown.falseornullas a return value from avalidatecall is meaningless (unless you yourself wish to do something with it).
method Model::reload(options?: object): undefined 📜
Reload the model in-place.
This method will create a query selecting this model from the database by its primary key. It will then take the columns from the select operation, and will apply the values to the model's fields in-place.
If a row is returned from the database, then the model's
fields will be updated, this.clearDirty() will be
called to clear the dirty status of the model, and
finally the model will be marked as persisted.
If no row is returned from the database, then this method will immediately return, and the model won't be updated.
If the model has no primary key field defined, then an exception will be thrown.
Notes:
- A primary key is required on the model for this method to work. If you don't have a primary key defined, then you will need to create your own "reload" operation.
Arguments:
options?:objectOptions to pass to the underlying QueryEngine.first call. If a
connectionproperty is present on this options object, then it will be used as the connection for this operation.Return value:
undefined
method Model::save(options?: object): boolean 📜
Persist the model to the database.
This method will either initiate an insert
operation against the model (if this.isPersisted()
returns false), or initiate an update operation (
if this.isPersisted() returns true).
This method will do nothing, and immediately return
false if the model is not dirty. If you provide
the option force: true as a property in the options
argument, then all fields will forcefully be marked as
dirty, using the current field's value as the "dirty"
value for each field, and then the model will be either
inserted or updated, based on the result from isPersisted.
Using force: true will essentially send and insert or
update operation through the connection that will update
ALL columns for the model row in the database, regardless
of if they were actually dirty or not.
At the end of this method--assuming the operation was successful--
this.clearDirty() will be called on the model instance to clear its
dirty state, and then the model will be marked as persisted.
Finally, true will be returned, letting the caller
know the operation completed successfully.
Arguments:
options?:objectOptions to pass to the underlying connection Connection.insert or Connection.update call. If a
connectionproperty is present on this options object, then it will be used as the connection for this operation.Return value:
boolean
trueif the model was persisted through the database, orfalseotherwise.falsedoesn't mean there was an error. Errors will be thrown.falsesimply means that the model had no dirty fields, so it was never sent to the database.
method Model::setAttributes(attributes: object | Model, noPrimaryKey: boolean): undefined 📜
Set attributes on the model via the provided object.
The provided object should contain keys that are
field names for each field you wish to set. The
value of each key will be what is set onto the field.
This method ignores virtual fields, so if any virtual
field names are supplied, then will be silently skipped.
This method is identical to calling modelInstance[fieldName] = value
on every key in the object provided.
Notes:
- Any
undefinedvalue in the provided object will be ignored, and no update will occur for the field.- If a raw object instead of a model instance is provided, then
hasOwnPropertyis called for each field name, and if the provided object doesn't contain its "own" property matching the field name, the field will be silently skipped, and not set.Arguments:
attributes:object|ModelThe attributes to set on the model. The keys of the model should be field names.
noPrimaryKey:booleanIf
true, then the primary key of the model (if any is defined) will be skipped, and won't be set, even if the providedattributesargument contains a value for the primary key.Return value:
undefined
method Model::setDataValue(fieldName: string, value: any): undefined 📜
Set the current value of any field on the model. The "current" value will be the dirty value if the field is dirty, or it will be the clean value of the field if the field isn't dirty.
This method is a "raw" set of the field's value
in that it won't call set on the field descriptor,
if any is defined. Instead, it will mark the field as
dirty by setting the value provided as an entry for
the field in the this._dirtyFieldData property of
the model instance. If the value set is equal to the
"clean value" of the field, as found in this._fieldData,
then the dirty entry for the field will be cleared (deleted)
instead.
Notes:
- This method will always call Model.updateDirtyID, invalidating all down-stream cache for this model instance.
Arguments:
fieldName:stringThe name of the field whose value you wish to set.
value:anyValue to set the field to. The will be sent through
field.type.castValueto cast the incoming value to the field's type.Return value:
undefined
static method Model::_getConnection(connection?: Connection): Connection 📜
Get the underlying connection bound to the model's class. Connection binding is optional, so this method can also be provided a connection. If a connection is provided, then it will simply be returned. Because Mythix ORM has no globals, this is a design pattern to supply a connection if you have one available, or fallback to a "bound" connection (if one can be found).
This method will return a connection in the following
order: 1) The provided connection argument, if supplied,
2) The connection property on the "model context" from
Model.getModelContext from AsyncLocalStorage,
if one is available, and 3) Finally the bound connection, if
available, which is found by searching the static Model._mythixBoundConnection
property of the class.
Notes:
- This is a low-level "global fallback" method. Any connection for a model will first be searched by calling Model.getConnection, which will call this static method if no connection can be found. The Model.getConnection will also search the model instance for a
connectionproperty, which can be supplied to any model when it is instantiated.- or via the provided
connectionargument to the Model.getConnection method (and eventually this method) will take priority over anyconnectionprovided by the "model context" fromAsyncLocalStorage. This can be an important detail when using Connection.transaction or Connection.createContext, because if a connection is directly specified by the user, the transaction connection will not take priority. So if you are using transactions or a connection context, be careful how you directly specify connections.Arguments:
connection?: ConnectionAn optional connection that can be provided. If provided, it will simply be returned. Otherwise, if not provided, or a falsy value, then attempt to fallback to the bound connection, if any is available.
Return value: Connection
Fetch all models from the database for this model type.
Notes:
- This will fetch ALL rows for the model. If this is not what you want, then construct a query first, and call
allfrom the query itself, i.e.User.where.firstName.EQ('Bob').all(options).Arguments:
options?:objectAn "options" object to pass off to the underlying Connection methods. If a
connectionkey is specified in this object, then that will be used as the connection for the operation. This can be important if for example you are calling this from atransaction, in which case you most certainly would want to provide theconnectionfor the transaction. If astream: trueoption is provided, then an async generator will be returned, allowing you to "stream" the rows from the database in batches. The defaultbatchSizeis500, but can be overridden by setting thebatchSizeoption to some valid positive number, orInfinityto pull everything at once. If thestreamoption is not specified, or isfalse, then all rows will be fetched from the database in batches, collected into an array, and returned only once all rows have been fetched. This is the default behavior.Return value: Array<Model>
Return all models of this type from the database.
static method Model::bindConnection(connection?: Connection): class extends Model 📜
A Connection instance will call
this method on a Model class to
bind the model to the connection. Overload
this to change the behavior of binding connections
to models. This method should return a model
class. The default behavior is to return
this class. However, you might return a
different class for example if you generated
a new class that inherited from this class.
Arguments:
connection?: ConnectionThe connection instance to bind to this model class.
Return value: class extends Model
static method Model::count(field?: string | Field, options?: object): number 📜
Count the rows in the database for this model.
Arguments:
field?:string|FieldA fully qualified field name, or a
Fieldinstance. If supplied, this is the column in the table that will be counted (i.e.COUNT(column)). If not supplied, then aCOUNT(*)type operation will be carried out.options?:objectAn "options" object to pass off to the underlying Connection methods. If a
connectionkey is specified in this object, then that will be used as the connection for the operation. This can be important if for example you are calling this from atransaction, in which case you most certainly would want to provide theconnectionfor the transaction.Return value:
numberReturn the number of models stored in the database for this model type.
static method Model::create(models: Array<Model> | Model | Array<object> | object, options?: object): Model 📜
Create (insert) new models into the database.
The models argument can be a single model instance,
a single object containing model attributes,
an array of model instances, or an array of
objects containing model attributes. This is
a "bulk" create method, though it can be used
to create a single model.
Arguments:
models: Array<Model> | Model |Array<object>|objectSpecify the model(s) to create.
options?:objectAn "options" object to pass off to the underlying Connection methods. If a
connectionkey is specified in this object, then that will be used as the connection for the operation. This can be important if for example you are calling this from atransaction, in which case you most certainly would want to provide theconnectionfor the transaction.Return value: Model
Return the model instance(s) created.
static method Model::defaultScope(query: QueryEngine): QueryEngine 📜
One can apply a "default scope" to any model simply by providing this static method on the model. By default it will simply return the QueryEngine instance (a query) that it was provided.
The way this works is simple. The caller provides the
query as the first and only argument. The user, by
overloading this method can then easily modify this
provided query, changing the "default scope" whenever
the model is used for queries. This can be used to set
a default order for a model, or to set default conditions
to apply to any query for the model. For example, let's say
you have a User model, and by default, you only want
to query against Users that have their active column
set to true. In order to do this, you could easily
provide a static defaultScope method on your model
class that would modify the base query. See the following example:
Example:
class User extends Model { static defaultScope(baseQuery) { // `baseQuery` is equal to `User.where` // without a default scope. return baseQuery.active.EQ(true).ORDER.ASC('User:createdAt'); } }Arguments:
query: QueryEngineThe query that you should add onto.
Return value: QueryEngine
static method Model::finalizeQuery(context: FinalizeQueryContext): QueryEngine 📜
Finalize a query before using it for database operations.
finalizeQuery is called on every query immediately
before it is used for a database operation. Its only purpose
is to potentially modify the query before the database operation
occurs. This can be extremely useful for things like "row level permissions",
or ensuring that a certain type of query always has certain conditions.
Because it is asynchronous by design, it is possible to finalize the query using other asynchronous operations; for example validating authentication tokens, or fetching user roles from the database.
This is called by Connection.finalizeQuery for each unique model found in the query.
Interface:
interface FinalizeQueryContext { type: 'create' | 'read' | 'updated' | 'delete'; // The operation type that is about to happen in the underlying database. query: QueryEngine; // The query being operated upon. Modify and return this. queryDepth: number; // The depth we are at while walking the query. Will be 0 for root level, 1 for first sub-query, etc... operationIndex: number; // The "operation stack" index we are at operation: object; // The "operation" on the query operation stack we are working on operations: Array<object>; // The query "operation stack" parent: object | null; // The parent "operation" contextKey: string; // The name of the key that this query is a value of for this "operation" object. This is usually "value" for most operations, but it could be something else. options: object; // The options passed into the operation by the user }Notes:
- "With great power comes great responsibility." Use
finalizeQueryintelligently. It can cause a noticeable performance hit, and can really make things hard to debug and understand if you don't clearly document.'create'isn't actually currently supported, since no queries are ever used in anINSERToperation. It is reserved for future use.Arguments:
context:FinalizeQueryContextAll provided values in a single context. You will want to modify
queryand return it... or if you don't modify it, simply return it. ThecontextKeymight be a little confusing. It is the name of the key the query is a value on. For example, in anEQoperation, this would be "value". i.e. anEQoperation looks something like the following on the operation stack:{ operator: 'EQ', value: query }. The reason it is provided is if you need to directly get or set a value on the operation frame (operation).Return value: QueryEngine
The query provided, possibly altered.
See also: Connection.finalizeQuery
Get the first (limit) rows from the database for this model type.
Notes:
- This will fetch the first rows for the model, in database order. If you wish to filter, and specify the order, then construct a query first, and call the
firstmethod from the query itself, i.e.User.where.firstName.EQ('Bob').ORDER('+User:firstName').first(options)Arguments:
limit?:number(Default:1)The number of model instances to fetch from the database.
options?:objectAn "options" object to pass off to the underlying Connection methods. If a
connectionkey is specified in this object, then that will be used as the connection for the operation. This can be important if for example you are calling this from atransaction, in which case you most certainly would want to provide theconnectionfor the transaction.Return value: Model | Array<Model>
Return
limitmodels of this type from the database. Iflimitisnull,undefined, or1, then a single model instance will be returned (orundefinedif nothing is found). If thelimitargument is more than1, then an array of model instances will be returned, or an empty array if nothing is found.
static method Model::getConcreteFieldCount(): number 📜
Count the number of concrete fields on the model.
"concrete" fields are non-virtual fields that are
backed by the database. A FOREIGN_KEY field is
a concrete field, so FOREIGN_KEY fields will be counted.
Return value:
numberThe number of concrete fields the model has.
static method Model::getContextValue(key: any, defaultValue?: any): any 📜
Get a value from the AsyncLocalStorage context.
AsyncLocalStorage is used primarily for two purposes: 1) to provide a connection to models, and 2) to pass a transaction connection down through the call stack. However, it can also be used for any "context" level values the user wishes to store.
Notes:
- An
AsyncLocalStoragecontext might not exist when this call is made, in which case this method will returnundefined, or thedefaultValueif any was provided.Arguments:
key:anyThe key for the value you wish to fetch. The underlying "context" provided by
AsyncLocalStorageis aMap, so the "key" can be any value.defaultValue?:anyThe default value to return if there is no current
AsyncLocalStoragecontext, or if the requested key is not found.Return value:
any
Get a specific model field by field name. This method
will return undefined if the specified field can not
be found on the model. This will find both concrete and
virtual fields that are defined on the model.
Notes:
- In Mythix ORM you never specify a field via its
columnName. You always use a field's definedfieldNameto match against a field. Using acolumnNamesimply won't work, unlesscolumnNameandfieldNamejust happen to have the same value.Arguments:
fieldName:stringThe specified field name to find. This is not the
columnNameof the field.Return value: Field
Get the fields for this model. You can optionally
specify the fieldNames argument, which will cause
the method to return only the fields specified by name.
If the fieldNames argument is provided, then the
return value will always be an array of fields. If
the fieldNames argument is not provided, then
the return value could be either an Array of fields,
or an object of fields, keyed by field name (depending
on how you defined your model fields).
Notes:
- The first time this method is called the model's fields will be built, and possibly modified. All fields will be turned into Field instances, and each field will be properly constructed to include required attributes, such as their parent
Model, theirfieldName, and theircolumnName. A model's fields are always initialized when the model is first bound to a connection, or when this method is first called.- In Mythix ORM you never specify a field via its
columnName. You always use a field's definedfieldNameto match against a field. Using acolumnNamesimply won't work, unlesscolumnNameandfieldNamejust happen to have the same value.Arguments:
fieldNames?:Array<string>An array of field names to fetch. If not provided then all model fields will be returned, including virtual fields.
static method Model::getForeignKeyFieldsMap(connection?: Connection): Map<string, array<object>> 📜
Return the foreign key relationships for the model.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
Return value:
Map<string, array<object>>The format is
Map[modelName] = [ { targetFieldName, sourceFieldName }, ... ]
static method Model::getForeignKeysTargetField(connection?: Connection, modelName: string, fieldName: string): object<{ targetFieldName, sourceFieldName }> 📜
Get a specific foreign key field's relationship information. This will be what is stored in the relationship field map for the specified target field. See Model.static getForeignKeyFieldsMap for more information.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
modelName:stringThe model name for which you wish to fetch foreign key fields from.
fieldName:stringThe field name for which you wish to fetch foreign key relational information about.
Return value:
object<{ targetFieldName, sourceFieldName }>This will be the relationship info for this foreign key field which will be an object of the shape
{ targetFieldName, sourceFieldName }.
static method Model::getForeignKeysTargetFieldNames(connection?: Connection, modelName: string): Array<string> 📜
Return all the foreign key target fields. This will return the target fields of all foreign key fields specified on the model.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
modelName:stringThe model name for which you wish to fetch foreign key fields from.
Return value:
Array<string>An array of all foreign key field info
Array<{ targetFieldName: string, sourceFieldName: string }>
static method Model::getForeignKeysTargetModelNames(connection?: Connection): Array<string> 📜
Return all the foreign key target model names. This will be all models targeted by all foreign keys defined by foreign key fields on this model. This will only return the models name's.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
Return value:
Array<string>The format is
Array[] = modelName
static method Model::getForeignKeysTargetModels(connection?: Connection): Map<string, Model> 📜
Return all the foreign key target models. This will be all models targeted by all foreign keys defined by foreign key fields on this model.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
Return value:
Map<string, Model>The format is
Map[modelName] = Model
Get the Model class for this model.
Arguments:
modelNameReturn value: class Model
static method Model::getModelContext(): object 📜
Get this Model class's "model context" from the AsyncLocalStorage context.
AsyncLocalStorage is used primarily for two purposes: 1) to provide a connection to models, and 2) to pass a transaction connection down through the call stack. However, it can also be used for any "context" level values the user wishes to store.
When a Connection.createContext or Connection.transaction
call is made, a "model context" (that is just an Object instance) is created for each
model the connection is aware of, and the connection instance is added to this
context, allowing models to lookup the "context connection" when a call to
Model._getConnection is made. By default, these "model contexts"
that are stored inside the AsyncLocalStorage context only contain a "connection"
property. However, these model contexts were designed as Object instances so that
the user may also use them, or so they can be used for future features. Each model
also has its own "model context" so that if the application is using more than
one connection, then a different connection can be specified for each model and
stored in the same AsyncLocalStorage context.
Notes:
- An
AsyncLocalStoragecontext might not exist when this call is made, in which case this method will simply return an empty object.Return value:
objectThe model class's "model context" stored in
AsyncLocalStorage. This will be an empty object if noAsyncLocalStoragecontext is available.
static method Model::getModelName(): string 📜
Get the model name for this model. By default
this will be the name of the class itself, i.e.
this.name. Overload this method to provide your
own model name (singular name).
Return value:
stringThe name the model.
static method Model::getPluralModelName(): string 📜
Get the plural model name for this model. By default this will be the singular name of the model, converted to plural using the Inflection library. Overload this method to provide your own plural name for the model.
Notes:
- This will return the "plural" name of the model.
Return value:
stringThe name the model in plural form.
See also: static Model.getSingularName
Get the primary key field of the model, if any is defined.
If no primary key field is defined, then this will return
undefined. A primary key is specified per-model by using
primaryKey: true on one (and only one) of the model's fields.
Return value: Field
static method Model::getPrimaryKeyFieldName(): string 📜
Get the name of the primary key field of the model,
if any is defined.
If no primary key field is defined, then this will return
undefined. A primary key is specified per-model by using
primaryKey: true on one (and only one) of the model's fields.
Return value:
string
static method Model::getQueryEngine(connection?: Connection, options?: object): QueryEngine 📜
This method is called any time a Model.where or
Model.$ property is accessed. It returns a query,
based off this model class (as the root model).
It will first call Model.static getUnscopedQueryEngine
to get the root query for the model, and then it will
call Model.static defaultScope to apply any
default scope to the root query. Finally, it will return
the query to the user to start interacting with.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
options?:objectAny extra options to pass to the QueryEngine constructor.
Return value: QueryEngine
static method Model::getQueryEngineClass(connection?: Connection): class QueryEngine 📜
This method is called every time a Model.where
or Model.$ property is accessed. It should return
a class that inherits from (or is) QueryEngine. By default,
it will call this.getConnection().getQueryEngineClass()
to get the query class defined in the connection
options. Though this can be overloaded per-model
(creating a different type of QueryEngine per-model),
the QueryEngine class to instantiate to use for queries will
generally be supplied by the connection.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
Return value: class QueryEngine
static method Model::getSingularName(): string 📜
Get the singular model name for this model. By default
this will be the name of the class itself, i.e.
this.name. You should probably overload Model.static getModelName
to provide your own model name, instead of overloading this method.
Notes:
- This will return the "singular" name of the model which is the same as Model.static getModelName.
- This method simply calls Model.static getModelName to get the singular model name.
Return value:
stringThe name the model in singular form.
See also: static Model.getPluralModelName, static Model.getModelName
This method is identical to Model.static getFields
except that it will always return an Array of fields, and the
fields will always be sorted by their fieldName.
Notes:
- In Mythix ORM you never specify a field via its
columnName. You always use a field's definedfieldNameto match against a field. Using acolumnNamesimply won't work, unlesscolumnNameandfieldNamejust happen to have the same value.Arguments:
fieldNames?:Array<string>An array of field names to fetch. If not provided then all model fields will be returned, including virtual fields.
Return value: Array<Field>
static method Model::getTableName(connection?: Connection): string 📜
Get the table name for this model. By default Mythix ORM will take the model's name, and convert it to snake_case.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
Return value:
stringThe name of the table for this model.
static method Model::getUnscopedQueryEngine(connection?: Connection, options?: object): QueryEngine 📜
This method is called any time a query.unscoped()
call is made. It will return the query's "root class"
where with no Model.static defaultScope
scope applied. Calling "unscoped()" will reset the query,
so make sure you always call it first: Model.where.unscoped()...
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
options?:objectAny extra options to pass to the QueryEngine constructor.
Return value: QueryEngine
static method Model::getWhereWithConnection(options?: object { connection: Connection }): QueryEngine 📜
This method is called anytime a Model.where or Model.$
attribute is accessed. It will provide the instantiated
QueryEngine with the connection specified (if any).
A connection can be specified for example by doing Model.where(connection)
or Model.$(connection). This is generally only useful if you
have chosen not to bind your models to a connection.
Arguments:
options?:object { connection: Connection }An object, which if supplied, should contain a
connectionkey, specifying the connection. If no connection is provided, then this will fallback tothis.getConnection()to try and find the connection itself.Return value: QueryEngine
A QueryEngine instance (a query) for this model.
static method Model::hasField(fieldName: string): boolean 📜
Check if the model has the specified field by name.
If the specified field is found on the model, then
return true, otherwise false will be returned.
Notes:
- In Mythix ORM you never specify a field via its
columnName. You always use a field's definedfieldNameto match against a field. Using acolumnNamesimply won't work, unlesscolumnNameandfieldNamejust happen to have the same value.Arguments:
fieldName:stringThe specified field name to find. This is not the
columnNameof the field.Return value:
boolean
static method Model::hasRemoteFieldValues(): boolean 📜
Check if any of the model's fields have a "remote value"
as a defaultValue. A defaultValue method can itself
report that it is "remote", meaning it is a value provided
by the database itself. This method simply iterates all the
model's fields, and calls field.type.isRemote() on each field.
If field.type.isRemote() returns true for any field, then
this method will return true, otherwise it will return false.
Use this method to know if the model contains any fields whose
value is obtained directly from the database itself (i.e. primary key
date fields, etc...).
Return value:
boolean
static method Model::initializeFields(fields: Array<Field> | Set<Field> | Object<string, Field> | Map<string, Field>): Array<Field> | object<string, Field> 📜
Initialize all fields for the model. This will be called anytime a Model.static getFields call is made. However, it caches its results, so it will immediately return if the model's fields have already been initialized.
This method does a number of things in the process of "initializing"
model fields. It first ensures that every field is an instance of
Field. Second, it ensures that the Type of the
field is initialized (properly instantiated). Third, it ensures that
all required attributes of each field is present. Required attributes
are Model (the parent model), fieldName (the name of this field),
and columnName (the column name for the DB). columnName, if not
provided, will simply become fieldName.
Notes:
- The cache for built fields is stored directly on the input
fieldsargument, under a non-enumerable_mythixFieldsInitializedcache key.Arguments:
fields: Array<Field> | Set<Field> | Object<string, Field> | Map<string, Field>A list of fields to work off of. When this method is called by Model.static getFields, then this argument will be
static Model.fields.
static method Model::isForeignKeyTargetModel(connection?: Connection, modelName: string): boolean 📜
Check if the specified model is a model pointed to by a foreign key field.
Arguments:
connection?: ConnectionAn optional connection to pass through. This is needed if your models are not bound to a connection.
modelName:stringThe model name for which you wish to fetch foreign key fields from.
Return value:
boolean
trueif the specifiedmodelNamemodel is pointed to by one of the foreign key fields,falseotherwise.
static method Model::isModel(value: any): boolean 📜
Check to see if the provided value is
an instance of a Mythix ORM Model.
Unlike Model.static isModelClass, which
checks if a class is a Model, this will check
to see if an instance is an instance of a
Mythix ORM Model. It will return
true if the provided value is an instanceof
Model, or if the value's constructor
property has a truthy _isMythixModel property
(value.constructor._isMythixModel)
Arguments:
value:anyValue to check.
Return value:
boolean
static method Model::isModelClass(value: Function): boolean 📜
Use this method to check if a class
is a Mythix ORM model. It will return
true if the provided value is a class
that inherits from Model, or
if the provided value has an attribute
named _isMythixModel that is truthy.
Arguments:
value:FunctionValue to check.
Return value:
boolean
static method Model::iterateFields(callback: Function(context: IterationContext), fields?: Array<Field> | Set<Field> | Object<string, Field> | Map<string, Field> = null, sorted?: boolean = false): Array<any> 📜
Iterate all model fields. This is a convenience method to
iterate static Model.fields, and is needed as the fields
of a model can be an Array, an object, a Map, or a Set.
This method works a lot like Array.prototype.map. Any return
value from the provided callback will be pushed into an array
just like Array.prototype.map. The callback provided, when called,
will be provided a context object, as the single argument to
the callback.
At any time you can call the stop method provided via the context.
When called, iterateFields will stop iterating, and immediately
return an array of results returned by all calls to callback.
The provided context object has the following shape:
Interface:
interface IterationContext { field: Field; // The Field instance itself. fieldName: string; // The name of the field. fields: // All the model's fields. Array<Field> | Set<Field> | Object<string, Field> | index: string | number; // The current index into the list of fields. stop: Function; // A method that when called will halt iteration. isStopped: Function; // Call this method to see if iteration is about to be halted. }Arguments:
callback:Function(context: IterationContext)A callback method that will be called for every field on the model.
fields?: Array<Field> | Set<Field> | Object<string, Field> | Map<string, Field> (Default:null)An optional list of fields to use instead of
static Model.fields. This is handy if, for example, you want to iterate a sub-set of the model's fields, such as the "dirty" fields reported by the model.sorted?:boolean(Default:false)If
true, then sort the model fields before iterating. Iffalse, simply iterate the model's fields in their defined order.Return value:
Array<any>
Get the last (limit) rows from the database for this model type.
Notes:
- This will fetch the last rows for the model, in database order. If you wish to filter, and specify the order, then construct a query first, and call the
lastmethod from the query itself, i.e.User.where.firstName.EQ('Bob').ORDER('+User:firstName').last(options)- This works by telling the underlying query generator to invert the specified ORDER of the query, and then it selects the first
limitrows from the result.Arguments:
limit?:number(Default:1)The number of model instances to fetch from the database.
options?:objectAn "options" object to pass off to the underlying Connection methods. If a
connectionkey is specified in this object, then that will be used as the connection for the operation. This can be important if for example you are calling this from atransaction, in which case you most certainly would want to provide theconnectionfor the transaction.Return value: Model | Array<Model>
Return
limitmodels of this type from the database. Iflimitisnull,undefined, or1, then a single model instance will be returned (orundefinedif nothing is found). If thelimitargument is more than1, then an array of model instances will be returned, or an empty array if nothing is found.
static method Model::mergeFields(mergeFields?: Array<Field> | Set<Field> | Object<string, Field> | Map<string, Field>): Array<Field> | object<string, Field> 📜
Merge specified fields into this model's fields.
The mergeFields argument is optional. If not
provided, then this method will simply clone
the model's fields. If specified, then the fields
provided will be merged into the existing fields.
Merging takes place based on each field's fieldName
attribute. The mergeFields argument can be an
Array, an object, a Map, or a Set. Fields
are matched based on fieldName, but when a match
is found, it is completely overridden by what is
found in the mergeFields argument. In short, the
list of fields itself is merged, but the fields themselves
are not merged (a shallow merge). All input objects that
have keys (Object<string, Field> | Map<string, Field>)
must specify the fieldName of the field as the key.
If the input is an Array type (Array<Field> | Set<Field>)
then each field must contain a fieldName attribute, or
an exception will be thrown.</string,></string,>
Notes:
- Anywhere you see Field as an input in this documentation, you can also simply provide a raw object with the same shape, and it will be automatically converted to a Field instance for you.
Arguments:
static method Model::pluck(fields?: Array<string>, options?: object): Array<any> | Array<Array<any>> 📜
Pluck specific fields (columns) from the database for this model type.
Notes:
- This will pluck across ALL rows for the model, in database order. If you wish to filter and limit, and specify the order, then construct a query first, and call the
pluckmethod from the query itself, i.e.User.where.firstName.EQ('Bob').LIMIT(50).ORDER('+User:firstName').pluck([ 'User:firstName' ], options)- In Mythix ORM you never specify a field via its
columnName. You always use a field's definedfieldNameto match against a field. Using acolumnNamesimply won't work, unlesscolumnNameandfieldNamejust happen to have the same value.Arguments:
fields?:Array<string>An array of fully qualified field names to pluck from the underlying database table for this model. Do not use column names here... these must be fully qualified field names.
options?:objectAn "options" object to pass off to the underlying Connection methods. If a
connectionkey is specified in this object, then that will be used as the connection for the operation. This can be important if for example you are calling this from atransaction, in which case you most certainly would want to provide theconnectionfor the transaction.Return value:
Array<any>|Array<Array<any>>If only a single field is specified, then a flat array of values will be returned across all rows. If more than one field is specified, then an array of arrays (rows) will be returned for the fields specified.
static method Model::primaryKeyHasRemoteValue(): boolean 📜
Check to see if the primary key field (if any is defined)
has a "remote" default value. For example, an autoincrementing
primary key field would return true from this method, because
an autoincrementing field value is retrieved directly from the
database. This could return false, if for example, you were
using UUIDs, or XIDs for your primary key.
Return value:
boolean
trueif the primary key field of the model has a "remote"defaultValue,falseotherwise. Remoteness is checked viathis.getPrimaryKeyField().type.isRemote().
static method Model::setContextValue(key: any, value: any): any 📜
Set a value onto the AsyncLocalStorage context.
AsyncLocalStorage is used primarily for two purposes: 1) to provide a connection to models, and 2) to pass a transaction connection down through the call stack. However, it can also be used for any "context" level values the user wishes to store.
Notes:
- An
AsyncLocalStoragecontext might not exist when this call is made, in which case this method will do nothing, and silently return.Arguments:
key:anyThe key for the value you wish to set. The underlying "context" provided by
AsyncLocalStorageis aMap, so the "key" can be any value.value:anyThe value to set to the specified key.
Return value:
any
static method Model::toString(showFields?: boolean): string 📜
Like everywhere in Javascript, we can
call .toString() to a get a string
representation of our Model
class. The optional showFields argument,
if true, will list the models fields as well.
Without the showFields argument, the model
name alone will be returned as a string.
Arguments:
showFields?:booleanIf
true, then list the models fields.Return value:
string
static method Model::updateModelContext(value: object): undefined 📜
Update this Model class's "model context" from the AsyncLocalStorage context.
AsyncLocalStorage is used primarily for two purposes: 1) to provide a connection to models, and 2) to pass a transaction connection down through the call stack. However, it can also be used for any "context" level values the user wishes to store.
When a Connection.createContext or Connection.transaction
call is made, a "model context" (that is just an Object instance) is created for each
model the connection is aware of, and the connection instance is added to this
context, allowing models to lookup the "context connection" when a call to
Model._getConnection is made. By default, these "model contexts"
that are stored inside the AsyncLocalStorage context only contain a "connection"
property. However, these model contexts were designed as Object instances so that
the user may also use them, or so they can be used for future features. Each model
also has its own "model context" so that if the application is using more than
one connection, then a different connection can be specified for each model and
stored in the same AsyncLocalStorage context.
This method allows you to update this "model context" for the model. The value
argument must be an Object instance. You can specify any properties you want.
Just be cautious if you set a connection property, as you might overwrite any
connection currently set on the context. Any properties you set here will be available
in any child function calls (inside this context scope), and can be accessed via a
call to Model.getModelContext.
Notes:
- An
AsyncLocalStoragecontext might not exist when this call is made, in which case this method will simply return an empty object.Arguments:
value:objectThe new properties you wish to merge with the current "model context".
Return value:
undefined
method Model::toJSON(): object 📜
Return a raw Object of the model's attributes,
ready to be passed through JSON.stringify. This
method is nearly identical to Model.getAttributes
except that it always inserts the primary key of the model
(if the model has one) first. The other difference
between this method and Model.getAttributes
is that this method will call field.type.serialize on
each field value.
Return value:
objectAll model attributes, ready to be serialized.
See also: Type.serialize
method Model::toString(): string 📜
Get a string representation of this model.
Return value:
stringThe model's name and attributes as a string.
method Model::updateDirtyID() 📜
Update the this._dirtyID cache key of the model.
This is called any time a field is marked as "dirty" on the model.
The _dirtyID property of a model is an instance of
a CacheKey that is intended to be used for
caching systems. The CacheKey instance can
be used for a key into a WeakMap, which can cache things.
Because this is updated to a new instance of a CacheKey
any time any field on the model is marked as dirty,
any cache for this model will be invalidated as soon
as any field on the model is dirty.
- Associations
- Certifications
- Connection Binding
- Home
- Models
- Queries
- TypeScript
- Types Reference
-
namespace AsyncStore
- function getContextStore
- function getContextValue
- function runInContext
- function setContextValue
-
namespace Helpers
- function checkDefaultValueFlags
- function defaultValueFlags
- function getDefaultValueFlags
- property FLAG_LITERAL
- property FLAG_ON_INITIALIZE
- property FLAG_ON_INSERT
- property FLAG_ON_STORE
- property FLAG_ON_UPDATE
- property FLAG_REMOTE
-
namespace MiscUtils
- function collect
- function valueToDateTime
-
namespace ModelUtils
- function parseQualifiedName
-
namespace QueryUtils
- function generateQueryFromFilter
- function mergeFields
- function parseFilterFieldAndOperator
-
class AverageLiteral
- method static isAggregate
- method toString
-
class BigIntType
- property Default
- method castToType
- method constructor
- method isValidValue
- method static getDisplayName
- method toString
-
class BlobType
- method castToType
- method constructor
- method isValidValue
- method static getDisplayName
- method toString
-
class BooleanType
- method castToType
- method isValidValue
- method static getDisplayName
- method toString
-
class CacheKey
- method constructor
- method valueOf
-
class CharType
- method castToType
- method isValidValue
- method static getDisplayName
- method toString
-
class ConnectionBase
- property _isMythixConnection
- property DefaultQueryGenerator
- property dialect
- property Literals
- method _averageLiteralToString
- method _bigintTypeToString
- method _blobTypeToString
- method _booleanTypeToString
- method _charTypeToString
- method _countLiteralToString
- method _datetimeTypeToString
- method _dateTypeToString
- method _distinctLiteralToString
- method _escape
- method _escapeID
- method _fieldLiteralToString
- method _getFromModelCache
- method _integerTypeToString
- method _maxLiteralToString
- method _minLiteralToString
- method _numericTypeToString
- method _realTypeToString
- method _setToModelCache
- method _stringTypeToString
- method _sumLiteralToString
- method _textTypeToString
- method _uuidV1TypeToString
- method _uuidV3TypeToString
- method _uuidV4TypeToString
- method _uuidV5TypeToString
- method _xidTypeToString
- method addColumn
- method addIndex
- method aggregate
- method alterColumn
- method alterTable
- method average
- method buildConnectionContext
- method bulkModelOperation
- method constructor
- method convertDateToDBTime
- method count
- method createContext
- method createQueryGenerator
- method createTable
- method createTables
- method destroy
- method destroyModels
- method dirtyFieldHelper
- method dropColumn
- method dropIndex
- method dropTable
- method dropTables
- method ensureAllModelsAreInstances
- method escape
- method escapeID
- method exists
- method finalizeQuery
- method findModelField
- method getContextValue
- method getDefaultFieldValue
- method getDefaultOrder
- method getField
- method getLockMode
- method getModel
- method getModels
- method getOptions
- method getQueryEngineClass
- method getQueryGenerator
- method insert
- method isStarted
- method literalToString
- method max
- method min
- method parseQualifiedName
- method pluck
- method prepareAllModelsAndSubModelsForOperation
- method prepareAllModelsForOperation
- method query
- method registerModel
- method registerModels
- method runSaveHooks
- method select
- method setContextValue
- method setPersisted
- method setQueryGenerator
- method splitModelAndSubModels
- method stackAssign
- method start
- method static getLiteralClassByName
- method static isConnection
- method static isConnectionClass
- method static Literal
- method stop
- method sum
- method toQueryEngine
- method transaction
- method truncate
- method typeToString
- method update
- method updateAll
- method upsert
-
class CountLiteral
- method static isAggregate
- method static isFieldRequired
- method toString
-
class DateTimeType
- property Default
- method castToType
- method constructor
- method deserialize
- method isValidValue
- method serialize
- method static getDisplayName
- method toString
-
class DateType
- property Default
- method castToType
- method constructor
- method deserialize
- method isValidValue
- method serialize
- method static getDisplayName
- method toString
-
class DistinctLiteral
- method toString
-
class Field
- property _isMythixField
- property allowNull
- property defaultValue
- property fieldName
- property get
- property index
- property primaryKey
- property set
- property type
- property unique
- property validate
- method clone
- method constructor
- method setModel
- method static isField
- method static isFieldClass
-
class FieldLiteral
- method toString
- class FieldScope
-
class ForeignKeyType
- method castToType
- method constructor
- method getOptions
- method getTargetField
- method getTargetFieldName
- method getTargetModel
- method getTargetModelName
- method initialize
- method isValidValue
- method parseOptionsAndCheckForErrors
- method static getDisplayName
- method static isForeignKey
- method toString
-
class IntegerType
- property Default
- method castToType
- method constructor
- method isValidValue
- method static getDisplayName
- method toString
-
class Literal
- method constructor
-
class LiteralBase
- property _isMythixLiteral
- method constructor
- method definitionToField
- method fullyQualifiedNameToDefinition
- method static isAggregate
- method static isLiteral
- method static isLiteralClass
- method static isLiteralType
- method toString
- method valueOf
-
class LiteralFieldBase
- method constructor
- method getField
- method getFullyQualifiedFieldName
- method static isFieldRequired
- method valueOf
-
class MaxLiteral
- method static isAggregate
- method toString
-
class MinLiteral
- method static isAggregate
- method toString
-
class Model
- property _isMythixModel
- method _castFieldValue
- method _constructField
- method _constructFields
- method _constructor
- method _getConnection
- method _getDirtyFields
- method _getFieldValue
- method _initializeFieldData
- method _initializeModelData
- method _setFieldValue
- method clearDirty
- method constructor
- method destroy
- method getAttributes
- method getConnection
- method getDataValue
- method getDirtyFields
- method getOptions
- method hasValidPrimaryKey
- method isDirty
- method isPersisted
- method onAfterCreate
- method onAfterSave
- method onAfterUpdate
- method onBeforeCreate
- method onBeforeSave
- method onBeforeUpdate
- method onValidate
- method reload
- method save
- method setAttributes
- method setDataValue
- method static _getConnection
- method static all
- method static bindConnection
- method static count
- method static create
- method static cursor
- method static defaultScope
- method static finalizeQuery
- method static first
- method static getConcreteFieldCount
- method static getContextValue
- method static getField
- method static getFields
- method static getForeignKeyFieldsMap
- method static getForeignKeysTargetField
- method static getForeignKeysTargetFieldNames
- method static getForeignKeysTargetModelNames
- method static getForeignKeysTargetModels
- method static getModel
- method static getModelContext
- method static getModelName
- method static getPluralModelName
- method static getPrimaryKeyField
- method static getPrimaryKeyFieldName
- method static getQueryEngine
- method static getQueryEngineClass
- method static getSingularName
- method static getSortedFields
- method static getTableName
- method static getUnscopedQueryEngine
- method static getWhereWithConnection
- method static hasField
- method static hasRemoteFieldValues
- method static initializeFields
- method static isForeignKeyTargetModel
- method static isModel
- method static isModelClass
- method static iterateFields
- method static last
- method static mergeFields
- method static pluck
- method static primaryKeyHasRemoteValue
- method static setContextValue
- method static toString
- method static updateModelContext
- method toJSON
- method toString
- method updateDirtyID
-
class ModelScope
- method _getField
- method AND
- method CROSS_JOIN
- method DISTINCT
- method EXISTS
- method Field
- method FULL_JOIN
- method GROUP_BY
- method HAVING
- method INNER_JOIN
- method JOIN
- method LEFT_JOIN
- method LIMIT
- method mergeFields
- method NOT
- method OFFSET
- method OR
- method ORDER
- method PROJECT
- method RIGHT_JOIN
-
class ModelType
- method fieldNameToOperationName
- method initialize
-
class ModelsType
- method fieldNameToOperationName
- method initialize
-
class NumericType
- method castToType
- method constructor
- method isValidValue
- method static getDisplayName
- method toString
-
class ProxyClass
- property APPLY
- property AUTO_CALL
- property AUTO_CALL_CALLED
- property AUTO_CALL_CALLER
- property CALLABLE
- property CONSTRUCT
- property DEFINE_PROPERTY
- property DELETE_PROPERTY
- property GET
- property GET_OWN_PROPERTY_DESCRIPTOR
- property GET_PROTOTYPEOF
- property HAS
- property IS_EXTENSIBLE
- property MISSING
- property OWN_KEYS
- property PREVENT_EXTENSIONS
- property PROXY
- property SELF
- property SET
- property SET_PROTOTYPEOF
- property shouldSkipProxy
- property TARGET
- method ___autoCall
- method ___call
- method constructor
-
class QueryEngine
- method all
- method average
- method constructor
- method count
- method cursor
- method destroy
- method exists
- method finalizeQuery
- method first
- method getFieldScopeClass
- method getModelScopeClass
- method last
- method max
- method MERGE
- method min
- method Model
- method pluck
- method sum
- method toString
- method unscoped
- method updateAll
-
class QueryEngineBase
- method _fetchScope
- method _inheritContext
- method _newFieldScope
- method _newModelScope
- method _newQueryEngineScope
- method _pushOperationOntoStack
- method clone
- method constructor
- method filter
- method getAllModelsUsedInQuery
- method getConnection
- method getFieldScopeClass
- method getModel
- method getModelScopeClass
- method getOperationContext
- method getOperationStack
- method getQueryEngineClass
- method getQueryEngineScope
- method getQueryEngineScopeClass
- method getQueryID
- method isLastOperationCondition
- method isLastOperationControl
- method isModelUsedInQuery
- method logQueryOperations
- method map
- method queryHasConditions
- method queryHasJoins
- method static generateID
- method static getQueryOperationInfo
- method static isQuery
- method static isQueryOperationContext
- method walk
-
class QueryGeneratorBase
- method _averageLiteralToString
- method _countLiteralToString
- method _distinctLiteralToString
- method _fieldLiteralToString
- method _maxLiteralToString
- method _minLiteralToString
- method _sumLiteralToString
- method constructor
- method escape
- method escapeID
- method getConnection
- method getFieldDefaultValue
- method getIndexFieldsFromFieldIndex
- method setConnection
- method stackAssign
- method toConnectionString
-
class RealType
- method castToType
- method constructor
- method isValidValue
- method static getDisplayName
- method toString
-
class SerializedType
- method castToType
- method constructor
- method deserialize
- method getOptions
- method initialize
- method isDirty
- method isValidValue
- method onSetFieldValue
- method serialize
- method static getDisplayName
- method toString
-
class StringType
- method castToType
- method constructor
- method isValidValue
- method static getDisplayName
- method toString
-
class SumLiteral
- method static isAggregate
- method toString
-
class TextType
- method castToType
- method constructor
- method isValidValue
- method static getDisplayName
- method toString
-
class Type
- property _isMythixFieldType
- property clone
- method castToType
- method clone
- method constructor
- method deserialize
- method exposeToModel
- method getDisplayName
- method getField
- method getModel
- method initialize
- method isDirty
- method isForeignKey
- method isRelational
- method isRemote
- method isValidValue
- method isVirtual
- method onSetFieldValue
- method serialize
- method setField
- method setModel
- method static instantiateType
- method static isSameType
- method static isType
- method static isTypeClass
- method static wrapConstructor
- method toConnectionType
-
class UUIDV1Type
- property Default
- method castToType
- method getArgsForUUID
- method isValidValue
- method static getDisplayName
- method validateOptions
-
class UUIDV3Type
- property Default
- method castToType
- method getArgsForUUID
- method isValidValue
- method static getDisplayName
- method validateOptions
-
class UUIDV4Type
- property Default
- method castToType
- method getArgsForUUID
- method isValidValue
- method static getDisplayName
- method validateOptions
-
class UUIDV5Type
- property Default
- method castToType
- method getArgsForUUID
- method isValidValue
- method static getDisplayName
- method validateOptions
-
class XIDType
- property Default
- method castToType
- method isValidValue
- method static getDisplayName