ORM: Extending Models
Introduction
All the Athenna models extends the Model
class of the @athenna/database
package. This class
provides everything that a model needs to communicate with database in the best way possible. But sometimes you may need to write your own methods depending on your business
logic and to save some time. You will see at this page how you can easily create your own static and instance methods for your models.
tip
Also, we recommend you to take a look at the implementation of the Model
class, this way you
could have more knowledge about all the methods available for your in the this
property when implementing your own methods.
Writing static methods
Let's start by defining a new static method in our User
model that will retrieve a user and also load relationships:
import { Model } from '@athenna/database'
export class User extends Model {
static async findWith(relationName, where = {}) {
const query = this.query().with(relationName)
// Verify if the where object is not
// empty to apply it in the query.
if (Object.keys(where).length) {
query.where(where)
}
return this.query().with(relationName).find()
}
/*...*/
}
Now we can start finding our user with his relations with a little less code:
const user = await User.findWith('posts.comments', { id: 1 })
Let's implement another method that will get all the users that were created in the last 15 minutes ordering then by name:
import { Model } from '@athenna/database'
export class User extends Model {
static async getRecentlyCreatedUsers() {
const nowDate = new Date()
const nowDateLessFifteenMinutes = new Date(nowDate - 15 * 60000)
return this.query()
.whereBetween('createdAt', [nowDate, nowDateLessFifteenMinutes])
.findMany()
}
/*...*/
}
Calling our new static method:
const recentlyUsers = await User.getRecentlyCreatedUsers()
Writing instance methods
You can also implement your own instance methods for your models. Let's implement a new instance method that will confirm the user email:
import { Model } from '@athenna/database'
export class User extends Model {
async confirmEmailNow() {
this.emailVerifiedAt = new Date()
await this.save()
}
/*...*/
}
Now we can easily confirm the user email with one method call:
const user = await User.find()
await user.confirmEmailNow()
Now let's implement a method that will load the user posts if they are not loaded and also get the oldest post of the user:
import { Model } from '@athenna/database'
export class User extends Model {
async getOldestPost() {
if (!this.posts) {
await this.load('posts', query => query.oldest())
}
return this.posts[0]
}
/*...*/
}
Using our new method:
const user = await User.find()
const oldestPost = await user.getOldestPost()
tip
Always be carefully to not break the single responsibility principle of SOLID
when
implementing your own model methods. But you are free to do whatever you want with Athenna 😎🤙. All this methods implementation will always depend on your business logic and
creativity.