A model defines an entity schema that will be handled by Pinia ORM. You can visualize a model as a table definition in a database. You can use models wherever your application needs to manage a collection of entities, whether they actually correspond to a database or not. Models encapsulate most of the functionality that you'll need to work with your data.
You can create a model by defining a new class that extends the Pinia ORM base Model
. All models require two static properties, an entity
and fields
property.
The following example sets up a new model that can be used to manage users:
import { Model } from 'pinia-orm'class User extends Model { static entity = 'users' static fields () { return { id: this.attr(null), name: this.attr('John Doe') } }}
entity
is a property that identifies a model, similar to the name of a database table. Each model's entity
name must be unique!
All models will create a Pinia module by their entity property and are found in state.entities
. In our example above, we will have created state.entities.users
. The default namespace entities
can be configured during installation.
fields
is a required property method that returns an object of field attributes to the model's schema. It maps data to their respective fields. It should return an object of key-value pairs consisting of the field name , and attribute definitions.
Pinia ORM supports the most common Javascript datatypes including primitives, object literals, and arrays. These datatypes are defined using various field attributes. The most common type of attribute you'll come across is the generic attribute type.
Attributes take a single argument – the fields default value. This default value is used in the event the field is missing when inserting data.
:::tip Attribute Decorators Typescript users can define attributes using decorators. To learn more about these, please take a look at the Decorators section. :::
Generic attributes can be defined using this.attr(...)
. This type of attribute, unlike other attributes, will take any datatype as it's default value, including String
, Number
, Boolean
, Object
and Array
.
The following example defines id
and name
fields on a user model using the generic attribute type:
class User extends Model { static entity = 'users' static fields () { return { id: this.attr(null), name: this.attr('John Doe') } }}
string
TypeString attributes can be defined using this.string(...)
. This type of attribute provides casting and will convert any given value to String
. The default value can be any string, including an empty string.
The following example defines the name
field on a user model using the string attribute:
class User extends Model { static entity = 'users' static fields () { return { ... name: this.string('') } }}
This attribute will ensure a given value is cast as a string. For example, if name
receives a value of false
or null
, it will become 'false'
or 'null'
.
This attribute may also have null
as a default value. However, to prevent casting, you will want to chain nullable()
to ensure the value can be set appropriately.
{ ... name: this.string(null).nullable()}
number
TypeNumber attributes can be defined using this.number(...)
. This type of attribute provides casting and will convert any given value to Number
. The default value can be any integer.
The following example defines the id
field on a user model using the number attribute:
class User extends Model { static entity = 'users' static fields () { return { id: this.number(0) ... } }}
This attribute will ensure a given value is cast as a number. For example, if id
receives a value of false
, it will become 0
, null
will become 0
, '123'
will become 123
, and so on.
This attribute may also have null
as a default value. However, to prevent casting, you will want to chain nullable()
to ensure the value can be set appropriately.
{ ... name: this.number(null).nullable()}
boolean
TypeBoolean attributes can be defined using this.boolean(...)
. This type of attribute provides casting and will convert any given value to Boolean
. The default value can be either true
or false
.
The following example defines the active
field on a user model using the boolean attribute:
class User extends Model { static entity = 'users' static fields () { return { ... active: this.boolean(false) } }}
This attribute will ensure a given value is cast as a boolean. Any truthy or falsy value will be cast accordingly. For example, if active
receives a value of 0
or null
, it will become false
. Likewise, if it receives a value of 1
or 'yes'
(non-empty string) it will become true
.
This attribute may also have null
as a default value. However, to prevent casting, you will want to chain nullable()
to ensure the value can be set appropriately.
{ ... active: this.boolean(null).nullable()}
uid
TypeUID attribute is the special attribute that works similarly to "Autoincrement" column type in RDB. When you try to save a record without the value set to the UID field, it will generate a unique ID automatically.
class User extends Model { static entity = 'users' static fields () { return { id: this.uid(), name: this.string('') } }}
This attribute will generate a unique string value using the uuid package with v1
method that looks something like 2c5ea4c0-4067-11e9-8bad-9b1deb4d3b7d
.
const user = useRepo(User).make()user.id // <- '2c5ea4c0-4067-11e9-8bad-9b1deb4d3b7d'
You can define a relationship between different models using relation attributes such as this.hasMany
, this.belongsTo
, etc. To learn more about these, please take a look at Relationships page.
All models must have a primary key field. The primary key serves as an index key that Pinia ORM will use to persist entities to the store by it's value.
By default, Pinia ORM will look for a primary key field called id
.
class User extends Model { static entity = 'users' static fields () { return { id: this.attr(null) ... } }}
The primary key can be mapped to any field that will have a unique value by defining the static primaryKey
property on a model.
The following example configures a user model to identify the field myId
as the primary key:
class User extends Model { static entity = 'users' static primaryKey = 'myId' static fields () { return { myId: this.attr(null) ... } }}
If a model is missing a primary key field definition, Pinia ORM will generate a primary key field automatically during database registration. The generated field will be configured using the uid
attribute type and named id
unless the static primaryKey
property is defined on a model.
The following example sets up a user model without an id
primary key field:
class User extends Model { static entity = 'users' static fields () { return { name: this.attr('') } }}
Pinia ORM will recognize the model is missing an id
field and will generate one in it's absence. The model will now be configured as follows:
class User extends Model { static entity = 'users' static fields () { return { id: this.uid(), // The auto-generated primary key field. name: this.attr('') } }}
The same principle applies to a model with a custom primary key definition. Pinia ORM will generate a primary key field using the name defined as the static primaryKey
property.
The following example sets up a user model configured with a primaryKey
property but without a corresponding primary key field:
class User extends Model { static entity = 'users' static primaryKey = 'myId' static fields () { return { name: this.attr('') } }}
Pinia ORM will recognize a custom primaryKey
has been defined but is unable to locate the corresponding field definition, and will generate one in it's absence. The model will now be configured as follows:
class User extends Model { static entity = 'users' static primaryKey = 'myId' static fields () { return { myId: this.uid(), // The auto-generated custom primary key field. name: this.attr('') } }}