Files
TinyORM/docs/database/seeding.mdx
silverqx 978f9160fb docs bugfix class vs className 😱
[skip ci]
2024-08-16 20:40:22 +02:00

153 lines
5.7 KiB
Plaintext

---
sidebar_position: 3
sidebar_label: Seeding
description: TinyORM includes the ability to seed your database with data using seed classes. The DatabaseSeeder class is considered as the root seeder. From this class, you may use the `call` method to run other seed classes, allowing you to control the seeding order.
keywords: [c++ orm, database, seeder, seeding, tinyorm]
---
import Link from '@docusaurus/Link'
# Database: Seeding
- [Introduction](#introduction)
- [Writing Seeders](#writing-seeders)
- [Calling Additional Seeders](#calling-additional-seeders)
- [Running Seeders](#running-seeders)
## Introduction
<div className="api-stability alert alert--success">
<Link to='/stability#stability-indexes'>__Stability: 2__</Link> - Stable
</div>
TinyORM includes the ability to seed your database with data using seed classes. All seed classes should be stored in the `database/seeders` directory. The `DatabaseSeeder` class is considered as the root seeder. From this class, you may use the `call` method to run other seed classes, allowing you to control the seeding order.
:::tip
[Mass assignment protection](tinyorm/getting-started.mdx#mass-assignment) is automatically disabled during database seeding.
:::
## Writing Seeders
To generate a seeder, execute the `make:seeder` `tom` command. A new seeder will be placed in the `database/seeders` directory relative to the current <abbr title='Current working directory'>pwd</abbr>:
```bash
tom make:seeder UserSeeder
```
:::tip
You can omit the `Seeder` word in the class name, `tom` appends it for you.
:::
A seeder class only contains one method by default: `run`. This method is called when the `db:seed` tom command is executed. Within the `run` method, you may insert data into your database however you wish. You may use the [query builder](database/query-builder.mdx#insert-statements) to manually insert data.
As an example, let's modify the default `DatabaseSeeder` class and add a database insert statement to the `run` method:
```cpp
#pragma once
#include <tom/seeder.hpp>
namespace Seeders
{
/*! Main database seeder. */
struct DatabaseSeeder : Seeder
{
/*! Run the database seeders. */
void run() override
{
DB::table("users")->insert({"name", "email"},
{
{"1. user", "user1@example.com"},
{"2. user", "user2@example.com"},
});
}
};
} // namespace Seeders
```
:::tip
The multi-insert [`insert`](database/query-builder.mdx#multi-insert-overload) method overload is ideal for seeding data.
:::
### Calling Additional Seeders
Within the `DatabaseSeeder` class, you may use the `call` method to execute additional seed classes. Using the `call` method allows you to break up your database seeding into multiple files so that no single seeder class becomes too large. The `call` method accepts the template parameter pack of seeder classes that should be executed:
```cpp
/*! Run the database seeders. */
void run() override
{
call<UserSeeder, PostSeeder, CommentSeeder>();
}
```
#### Call with additional arguments
The `call` method allows to pass additional arguments to the seeder/s, but it has additional requirements.
If you define a `run` method without parameters then this method is called using the virtual dispatch (polymorphism) and in this case, you should use the `override` specifier.
If you define your `run` method eg. like this `run(bool shouldSeed)` or whatever parameters you want, then this method is called using the fold expression (virtual dispatch is not used in this case) so you can't use the `override` specifier and you must call the `call<>()` method with exactly the same arguments like the `run` method was defined with, in our example, it should look like this `call<ExampleSeeder>(true)`.
Let's demonstrate it on a small example, following is the `run` method in the root `DatabaseSeeder` class.
```cpp
/*! Run the database seeders. */
void run() override
{
// This value can be based eg. on data from the database
const auto shouldSeed = true;
call<UserSeeder>(shouldSeed);
}
```
The `run` method in the `UserSeeder` class.
```cpp
/*! Run the database seeders. */
void run(const bool shouldSeed)
{
if (!shouldSeed)
return;
DB::table("users")->insert({
{"name", "1. user"},
});
}
```
:::tip
The `call` method provides two shortcut methods, `callWith` and `callSilent` (no output from seeders).
:::
## Running Seeders
You may execute the `db:seed` tom command to seed your database. By default, the `db:seed` command runs the `Seeders::DatabaseSeeder` class, which may in turn invoke other seed classes. However, you may use the `--class` option to specify a specific seeder class to run individually:
```bash
tom db:seed
tom db:seed --class=UserSeeder
```
You may also seed your database using the `migrate`, `migrate:fresh` or `migrate:refresh` commands in combination with the `--seed` option. For example the `migrate:fresh` command drops all tables and re-run all of your migrations. This command is useful for completely re-building your database:
```bash
tom migrate:fresh --seed
```
:::tip
You can change the default seeders path as is described in the [`C preprocessor macros`](building/tinyorm.mdx#TINYTOM_SEEDERS_DIR), CMake provides the [`TOM_SEEDERS_DIR`](building/tinyorm.mdx#TOM_SEEDERS_DIR) option.
:::
#### Forcing Seeders To Run In Production
Some seeding operations may cause you to alter or lose data. In order to protect you from running seeding commands against your production database, you will be prompted for confirmation before the seeders are executed in the `production` environment. To force the seeders to run without a prompt, use the `--force` flag:
```bash
tom db:seed --force
```