search ESC

Searching…

No results for "".

Type at least 2 characters to search.

Docs

Seeding

Database seeders let you populate your SQLite tables with test or default data using simple seeder classes and expressive model factories.

Introduction

Magic includes the ability to seed your database with data using seed classes. All seed classes are stored in the lib/database/seeders directory. Seeders are useful for populating your database with test data during development.

Running Seeders

The primary way to seed your database is using Magic.seed() in your main.dart:

void main() async {
  await Magic.init(...);

  // Seed database in development
  if (kDebugMode) {
    final count = await DB.table('users').count();
    if (count == 0) {
      await Magic.seed([DatabaseSeeder()]);
    }
  }

  runApp(MagicApplication(...));
}

You may also seed specific seeders directly:

await Magic.seed([UserSeeder(), PostSeeder()]);

Writing Seeders

Generate a seeder using the CLI:

dart run magic:artisan make:seeder UserSeeder

A seeder class contains a single run method which is called when the seeder is executed:

import 'package:magic/magic.dart';
import '../factories/user_factory.dart';

class UserSeeder extends Seeder {
  @override
  Future run() async {
    await UserFactory().count(50).create();
  }
}

The DatabaseSeeder

The DatabaseSeeder is the entry point for all seeders. Use call() to run multiple seeders in order:

import 'package:magic/magic.dart';
import 'user_seeder.dart';
import 'post_seeder.dart';
import 'comment_seeder.dart';

class DatabaseSeeder extends Seeder {
  @override
  Future run() async {
    await call([
      UserSeeder(),
      PostSeeder(),
      CommentSeeder(),
    ]);
  }
}

Writing Factories

Factories define how to generate fake data for a model. Generate a factory using the CLI:

dart run magic:artisan make:factory User

A factory extends Factory and defines the model's default attributes:

import 'package:magic/magic.dart';
import '../../app/models/user.dart';

class UserFactory extends Factory {
  @override
  User newInstance() => User();

  @override
  Map definition() {
    return {
      'name': faker.person.name(),
      'email': faker.internet.email(),
      'password': 'password123',  // Use a consistent test password
      'is_active': true,
    };
  }
}

Available Faker Methods

Magic includes the Faker library for generating realistic test data:

// Person
faker.person.name()              // "John Doe"
faker.person.firstName()         // "John"
faker.person.lastName()          // "Doe"

// Internet
faker.internet.email()           // "[email protected]"
faker.internet.userName()        // "johndoe123"
faker.internet.domainName()      // "example.com"
faker.internet.uri('https')      // "https://example.com/path"

// Lorem
faker.lorem.word()               // "lorem"
faker.lorem.sentence()           // "Lorem ipsum dolor sit amet."
faker.lorem.sentences(3)         // Multiple sentences

// Address
faker.address.city()             // "New York"
faker.address.country()          // "United States"
faker.address.streetAddress()    // "123 Main St"

// Date
faker.date.dateTime()            // Random DateTime
faker.date.dateTimeBetween(start: startDate, end: endDate)

// Random
faker.randomGenerator.integer(100)    // 0-100
faker.randomGenerator.boolean()       // true/false
faker.randomGenerator.element(['a', 'b', 'c'])  // Random from list

Using Factories

// Create a single model (saved to DB)
final user = (await UserFactory().create()).first;

// Create 50 models
final users = await UserFactory().count(50).create();

// Create with state override
final admins = await UserFactory()
    .state({'role': 'admin'})
    .count(5)
    .create();

// Create without saving (in-memory only)
final mocks = UserFactory().count(10).make();

Factory States

Define reusable state transformations within your factory:

class UserFactory extends Factory {
  @override
  User newInstance() => User();

  @override
  Map definition() {
    return {
      'name': faker.person.name(),
      'email': faker.internet.email(),
      'role': 'user',
      'email_verified_at': Carbon.now().toIso8601String(),
    };
  }

  // State methods for common variations
  UserFactory admin() {
    return state({'role': 'admin'}) as UserFactory;
  }

  UserFactory unverified() {
    return state({'email_verified_at': null}) as UserFactory;
  }

  UserFactory inactive() {
    return state({'is_active': false}) as UserFactory;
  }
}

// Usage
await UserFactory().admin().count(3).create();
await UserFactory().unverified().count(10).create();

CLI Commands

Create Seeder

dart run magic:artisan make:seeder UserSeeder
dart run magic:artisan make:seeder User           # Auto-appends 'Seeder'

Output: Creates lib/database/seeders/user_seeder.dart

Create Factory

dart run magic:artisan make:factory User
dart run magic:artisan make:factory UserFactory   # Accepts either form

Output: Creates lib/database/factories/user_factory.dart

[!TIP] Use the --all flag with make:model to generate model, migration, seeder, and factory in one command: dart run magic:artisan make:model User --all