Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(orm): add more docs about ORM #153

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/database/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ with it using the `Database` facade. The `Database` facade provides a
lot of methods to perform database operations such as **creating,
dropping and listing databases/tables, running and reverting**
[**migrations**](/docs/database/migrations)**,**
[**transactions**](/docs/database/getting-started#id-database-transactions)**,
[**transactions**](/docs/database/getting-started#database-transactions)**,
queries, connecting to new databases and also closing these
connections.**

Expand Down Expand Up @@ -171,7 +171,7 @@ await Database.revertMigrations()
### Transactions

If you don't know what is a transaction you can
check [`clicking here`](/docs/database/getting-started#id-database-transactions)
check [`clicking here`](/docs/database/getting-started#database-transactions)

```typescript
import { Log } from '@athenna/logger'
Expand Down
2 changes: 1 addition & 1 deletion docs/database/migrations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ node artisan make:migration create_flights_table
:::tip

Migrations templates may be customized using the
[**template customization command**](https://athenna.io/docs/the-basics/cli/commands#id-registering-custom-templates).
[**template customization command**](https://athenna.io/docs/the-basics/cli/commands#registering-custom-templates).

:::

Expand Down
2 changes: 1 addition & 1 deletion docs/database/query-builder.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ const users = await Database.table('users')
```

To build more advanced `having()` statements, see the
[`havingRaw()`](/docs/database/query-builder#id-having-raw) method.
[`havingRaw()`](/docs/database/query-builder#having-raw) method.

#### Limit & Offset

Expand Down
24 changes: 12 additions & 12 deletions docs/digging-deeper/collections.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ new Collection({

#### `average()`

Alias for the [`avg()`](#id-avg) method
Alias for the [`avg()`](#avg) method

#### `avg()`

Expand Down Expand Up @@ -957,7 +957,7 @@ collection.get('middlename', () => 'default-value')

The groupBy method groups the collection's items into multiple collections by a given key:

> If you want to group the collection by keys as a plain object, see [mapToGroups](#id-mapToGroups)
> If you want to group the collection by keys as a plain object, see [mapToGroups](#mapToGroups)

```js
const collection = new Collection([
Expand Down Expand Up @@ -1683,27 +1683,27 @@ new Collection([1, 2, 3, 4])

#### `order()`

Alias for the [sort](#id-sort) method.
Alias for the [sort](#sort) method.

#### `orderDesc()`

Alias for the [sortDesc](#id-sortDesc) method.
Alias for the [sortDesc](#sortDesc) method.

#### `orderBy()`

Alias for the [sortBy](#id-sortBy) method.
Alias for the [sortBy](#sortBy) method.

#### `orderByDesc()`

Alias for the [sortByDesc](#id-sortByDesc) method.
Alias for the [sortByDesc](#sortByDesc) method.

#### `orderKeys()`

Alias for the [sortKeys](#id-sortKeys) method.
Alias for the [sortKeys](#sortKeys) method.

#### `orderKeysDesc()`

Alias for the [sortKeysDesc](#id-sortKeysDesc) method.
Alias for the [sortKeysDesc](#sortKeysDesc) method.

#### `pad()`

Expand Down Expand Up @@ -2323,7 +2323,7 @@ collection.sole('product', '=', 'Desk')

#### `some()`

Alias for the [contains](#id-contains) method.
Alias for the [contains](#contains) method.

#### `sort()`

Expand Down Expand Up @@ -2494,7 +2494,7 @@ sorted.all()

#### `sortKeysDesc()`

This method has the same signature as the [sortKeys](#id-sortkeys) method, but will sort the collection in the opposite order.
This method has the same signature as the [sortKeys](#sortkeys) method, but will sort the collection in the opposite order.

#### `splice()`

Expand Down Expand Up @@ -2886,11 +2886,11 @@ collection.all()

#### `unlessEmpty()`

Alias for the [`whenNotEmpty()`](#id-whenNotEmpty) method
Alias for the [`whenNotEmpty()`](#whenNotEmpty) method

#### `unlessNotEmpty()`

Alias for the [`whenEmpty()`](#id-whenEmpty) method
Alias for the [`whenEmpty()`](#whenEmpty) method

#### `unwrap()`

Expand Down
143 changes: 142 additions & 1 deletion docs/orm/extending-models.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,145 @@ See how to extend models implementations in Athenna Framework.

## Introduction

Coming soon...
All the Athenna models extends the
[`BaseModel`](https://github.com/AthennaIO/Database/blob/develop/src/models/BaseModel.ts)
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
[`BaseModel`](https://github.com/AthennaIO/Database/blob/develop/src/models/BaseModel.ts)
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:

```typescript
import { BaseModel } from '@athenna/database'

export class User extends BaseModel {
public static async findWith(relation: string, where: Partial<InstanceType<User>> = {}): Promise<User> {
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:

```typescript
const user = await User.findWith('posts', { 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:

```typescript
import { BaseModel } from '@athenna/database'

export class User extends BaseModel {
public static async getRecentlyCreatedUsers(): Promise<User[]> {
const nowDate = new Date()
const nowDateLessFifteenMinutes = new Date(nowDate - 15 * 60000)

return this.query()
.whereBetween('createdAt', [nowDate, nowDateLessFifteenMinutes])
.findMany()
}

/*...*/
}
```

Calling our new static method:

```typescript
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:

```typescript
import { BaseModel } from '@athenna/database'

export class User extends BaseModel {
public async confirmEmailNow() {
this.emailVerifiedAt = new Date()

await this.save()
}

/*...*/
}
```

Now we can easily confirm the user email with one
method call:

```typescript
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:

```typescript
import { type Post } from '#app/models/Post'
import { BaseModel } from '@athenna/database'

export class User extends BaseModel {
public async getOldestPost(): Promise<Post> {
if (!this.posts) {
await this.load('posts', query => query.oldest())
}

return this.posts[0]
}

/*...*/
}
```

Using our new method:

```typescript
const user = await User.find()
const oldestPost = await user.getOldestPost()
```

:::tip

Always be carefully to not break the single responsibility principle
of [`SOLID`](https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898)
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.

:::
Loading
Loading