Decorators
All of the ORM decorators can be imported as follows:
import {
column,
hasOne,
scope,
beforeSave,
beforeFind,
// ... and so on
} from '@ioc:Adonis/Lucid/Orm'
column
The column
decorator marks a model property as a database column.
import { column, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends BaseModel {
@column()
public email: string
}
You can also define any of the following optional properties.
Option | Description |
---|---|
columnName | The name of the column inside the database. If not defined, We will use the naming strategy to create the name. |
serializeAs | The property name to be used when serializing the model. Setting the value to null will remove the property from the serialized object. |
isPrimary | Mark column as primary. One model can only have one primary column. |
serialize | A custom function to handle the column value serialization. For example: Serialize luxon date objects to a string. |
prepare | A custom function to transform the value before it is saved inside the database. |
consume | A custom function to transform the value after fetching it from the database and before defining it on the model instance. |
meta | The meta object holds arbitrary metadata for the property. 3rd party libraries extending the model's functionality can use this property. |
import Encryption from '@ioc:Adonis/Core/Encryption'
import { column, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends BaseModel {
@column({
prepare: (value: string) => Encryption.encrypt(value),
consume: (value: string) => Encryption.decrypt(value),
})
public email: string
@column({
serializeAs: null
})
public password: string
}
column.date / column.dateTime
The column.date
decorator marks the column as a date. The decorator enforces the property type to be an instance of luxon.DateTime
.
The decorator self defines
the prepare
, consume
and the serialize
methods to ensure
- You are constantly working with an instance of
luxon.DateTime
in your codebase - The date is serialized as an ISO date
- The date is formatted correctly as per the underlying database driver.
import { DateTime } from 'luxon'
import { column, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends BaseModel {
@column.date()
public dob: DateTime
}
Additionally, you can also define autoCreate
and autoUpdate
options to always set/update the value when an insert or update query is executed.
You will mainly use these attributes with the createdAt
and updatedAt
timestamps.
class User extends BaseModel {
@column.dateTime({ autoCreate: true })
public createdAt: DateTime
@column.dateTime({ autoUpdate: true })
public updatedAt: DateTime
}
computed
You can use the computed
decorator to serialize a model property when converting the model instance to a JSON object.
import { column, computed, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends BaseModel {
@column()
public firstName: string
@column()
public lastName: string
@computed()
public get fullName() {
return `${this.firstName} ${this.lastName}`
}
}
Now serializing the model will include the fullName
as well.
const user = new User()
user.firstName = 'Harminder'
user.lastName = 'Virk'
console.log(user.serialize())
/**
{
firstName: 'Harminder',
lastName: 'Virk',
fullName: 'Harminder Virk'
}
*/
hasOne
The hasOne
decorator marks a property as a Has one relationship. It accepts a callback as the first argument. The callback must return the relationship model.
import { hasOne, HasOne, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends Model {
@hasOne(() => Profile)
public profile: HasOne<typeof Profile>
}
Optionally, you can define following options as the 2nd argument.
Option | Description |
---|---|
foreignKey | The foreign key for the relationship. You must define the model property name here and Lucid will infer the table column name automatically. |
localKey | The local key is the property name on the current model that forms a relationship with the foreign key |
serializeAs | The property name to be used when serializing the relationship. Setting the value to null will remove the relationship from the serialized object. |
onQuery | A callback to modify all relationship queries. The callback will run for all the select, update and delete operations executed using the relationship query builder. |
hasMany
The hasMany
decorator marks a property as a hasMany relationship. It accepts a callback as the first argument. The callback must return the relationship model.
import { hasMany, HasMany, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends Model {
@hasMany(() => Post)
public posts: HasMany<typeof Post>
}
Optionally, you can define following options as the 2nd argument.
Option | Description |
---|---|
foreignKey | The foreign key for the relationship. You must define the model property name here and Lucid will infer the table column name automatically. |
localKey | The local key is the property name on the current model that forms a relationship with the foreign key |
serializeAs | The property name to be used when serializing the relationship. Setting the value to null will remove the relationship from the serialized object. |
onQuery | A callback to modify all relationship queries. The callback will run for all the select, update and delete operations executed using the relationship query builder. |
belongsTo
The belongsTo
decorator marks a property as a belongsTo relationship. It accepts a callback as the first argument. The callback must return the relationship model.
import { belongsTo, BelongsTo, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends Model {
@belongsTo(() => Team)
public team: BelongsTo<typeof Team>
}
Option | Description |
---|---|
foreignKey | The foreign key for the relationship. In case of belongs to, the foreignKey must be on the current model |
localKey | The local key is the property name on the related model that forms a relationship with the foreign key |
serializeAs | The property name to be used when serializing the relationship. Setting the value to null will remove the relationship from the serialized object. |
onQuery | A callback to modify all relationship queries. The callback will run for all the select, update and delete operations executed using the relationship query builder. |
manyToMany
The manyToMany
decorator marks a property as a many to many relationship. It accepts a callback as the first argument. The callback must return the relationship model.
import { manyToMany, ManyToMany, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends Model {
@manyToMany(() => Subject)
public subjects: ManyToMany<typeof Subject>
}
Option | Description |
---|---|
pivotForeignKey | The foreign key of the current model inside the pivot table. |
pivotRelatedForeignKey | The foreign key of the related model inside the pivot table. |
localKey | The local key is the property name on the current model that forms a relationship with the foreign key |
relatedKey | The related key is the property name on the related model that forms a relationship with the foreign key |
serializeAs | The property name to be used when serializing the relationship. Setting the value to null will remove the relationship from the serialized object. |
onQuery | A callback to modify all relationship queries. The callback will run for all the select, update and delete operations executed using the relationship query builder. |
hasManyThrough
The hasManyThrough
decorator marks a property as a has many through relationship. It accepts an array of callbacks as the first argument.
- The first callback returns the related model
- The second callback returns the through model
import { hasManyThrough, HasManyThrough, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class Country extends Model {
@hasManyThrough([
() => Post,
() => User,
])
public posts: HasManyThrough<typeof Post>
}
Option | Description |
---|---|
foreignKey | The foreign key for the relationship. The foreign key forms the relationship between the current model and the through model. ie. The countryId on the User model. |
localKey | The local key is the property name on the current model that forms a relationship with the foreign key |
throughForeignKey | The foreign key that forms the relationship between the through and the related model. ie. The userId on the Post model. |
throughLocalKey | The local key on the through model that forms a relationship with the throughForeignKey . |
serializeAs | The property name to be used when serializing the relationship. Setting the value to null will remove the relationship from the serialized object. |
onQuery | A callback to modify all relationship queries. The callback will run for all the select, update and delete operations executed using the relationship query builder. |
beforeSave
The beforeSave
decorator registers a given function as a before hook invoked before the insert and the update query.
import { beforeSave, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends BaseModel {
@beforeSave()
public static async hashPassword(user: User) {
if (user.$dirty.password) {
user.password = await Hash.make(user.password)
}
}
}
The after save variant is also supported using the afterSave
decorator.
beforeCreate
The beforeCreate
decorator registers the function to be invoked just before the insert operation.
import { beforeCreate, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends BaseModel {
@beforeCreate()
public static assignAvatar(user: User) {
user.avatarUrl = getRandomAvatar()
}
}
You can use the afterCreate
decorator to define a hook that runs after creating a new row.
beforeUpdate
The beforeUpdate
decorator registers the function to be invoked just before the update operation.
import { beforeUpdate, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class User extends BaseModel {
@beforeUpdate()
public static async assignAvatar(user: User) {
user.avatarUrl = getRandomAvatar()
}
}
You can use the afterUpdate
decorator to define a hook that runs after updating a row.
beforeDelete
The beforeDelete
decorator registers the function to be invoked just before the delete operation.
import { beforeDelete, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class Post extends BaseModel {
@beforeDelete()
public static async removeFromCache(post: Post) {
await Cache.remove(`post-${post.id}`)
}
}
You can use the afterDelete
decorator to define a hook that runs after deleting a row.
beforeFind
The beforeFind
decorator registers the function to be invoked just before the find operation.
Find operations are one's that intentionally selects a single database row. For example:
Model.find()
Model.findBy()
Model.first()
import {
beforeFind,
BaseModel,
ModelQueryBuilderContract
} from '@ioc:Adonis/Lucid/Orm'
type PostQuery = ModelQueryBuilderContract<typeof Post>
class Post extends BaseModel {
@beforeFind()
public static withoutSoftDeletes(query: PostQuery) {
query.whereNull('deleted_at')
}
}
afterFind
You can use the afterFind
decorator to define a hook that runs after finding the row from the database.
The hook receives the model instance as the only argument.
import { afterFind, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class Post extends BaseModel {
@afterFind()
public static async processMarkdown(post) {
post.html = await markdownIt(post.body)
}
}
beforeFetch
The beforeFetch
decorator registers the function to be invoked just before the fetch operation.
All select queries except the find operations are considered as fetch operations.
import {
beforeFetch,
BaseModel,
ModelQueryBuilderContract
} from '@ioc:Adonis/Lucid/Orm'
type PostQuery = ModelQueryBuilderContract<typeof Post>
class Post extends BaseModel {
@beforeFetch()
public static withoutSoftDeletes(query: PostQuery) {
query.whereNull('deleted_at')
}
}
afterFetch
The afterFetch
decorator registers the function to be invoked after the fetch operation.
The after fetch hook receives an array of model instances as the only argument.
import { afterFetch, BaseModel } from '@ioc:Adonis/Lucid/Orm'
class Post extends BaseModel {
@afterFetch()
public static async processMarkdown(posts: Post[]) {
await Promise.all(posts.map((post) => {
return markdownIt(post.body)
}))
}
}
beforePaginate
The beforePaginate
decorator registers the function to be invoked just before the paginate operation.
import {
beforePaginate,
BaseModel,
ModelQueryBuilderContract
} from '@ioc:Adonis/Lucid/Orm'
type PostQuery = ModelQueryBuilderContract<typeof Post>
class Post extends BaseModel {
@beforePaginate()
public static withoutSoftDeletes(
[countQuery, query]: [PostQuery, PostQuery]
) {
countQuery.whereNull('deleted_at')
query.whereNull('deleted_at')
}
}
afterPaginate
The afterPaginate
decorator registers the function to be invoked after the paginate operation.
The after paginate hook receives an instance of the paginator .
import {
afterPaginate,
BaseModel,
ModelPaginatorContract
} from '@ioc:Adonis/Lucid/Orm'
type PostPaginator = ModelPaginatorContract<Post>
class Post extends BaseModel {
@afterPaginate()
public static async processMarkdown(paginator: PostPaginator) {
await Promise.all(paginator.all().map((post) => {
return markdownIt(post.body)
}))
}
}