Skip to content

Commit

Permalink
add: infer migration (#1086)
Browse files Browse the repository at this point in the history
* add: infer migration
  • Loading branch information
jondot authored Dec 17, 2024
1 parent f5a9032 commit 481e1d0
Show file tree
Hide file tree
Showing 16 changed files with 733 additions and 656 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

* feat: smart migration generator. you can now generate migration based on naming them for creating a table, adding columns, references, join tables and more. [https://github.com/loco-rs/loco/pull/1086](https://github.com/loco-rs/loco/pull/1086)
* feat: `cargo loco routes` will now pretty-print routes
* fix: guard jwt error behind feature flag. [https://github.com/loco-rs/loco/pull/1032](https://github.com/loco-rs/loco/pull/1032)
* fix: logger file_appender not using the seperated format setting. [https://github.com/loco-rs/loco/pull/1036](https://github.com/loco-rs/loco/pull/1036)
Expand Down
103 changes: 73 additions & 30 deletions docs-site/content/docs/the-app/models.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ impl super::_entities::users::ActiveModel {

# Crafting models

## Migrations
## The model generator

To add a new model _you have to use a migration_.
To add a new model the model generator creates a migration, runs it, and then triggers an entities sync from your database schema which will hydrate and create your model entities.

```
$ cargo loco generate model posts title:string! content:text user:references
Expand Down Expand Up @@ -181,20 +181,24 @@ You can generate an empty model:
$ cargo loco generate model posts
```

You can generate an empty model **migration only** which means migrations will not run automatically:

Or a data model, without any references:

```
$ cargo loco generate model --migration-only posts
$ cargo loco generate model posts title:string! content:text
```

Or a data model, without any references:
## Migrations

Other than using the model generator, you drive your schema by *creating migrations*.

```
$ cargo loco generate model posts title:string! content:text
$ cargo loco generate migration <name of migration> [name:type, name:type ...]
```

This creates a migration in the root of your project in `migration/`.
You can now apply it:

You can apply it:

```
$ cargo loco db migrate
Expand All @@ -210,6 +214,63 @@ Loco is a migration-first framework, similar to Rails. Which means that when you

This enforces _everything-as-code_, _reproducibility_ and _atomicity_, where no knowledge of the schema goes missing.

**Naming the migration is important**, the type of migration that is being generated is inferred from the migration name.

### Create a new table

* Name template: `Create___`
* Example: `CreatePosts`

```
$ cargo loco g migration CreatePosts title:string content:string
```

### Add columns

* Name template: `Add___To___`
* Example: `AddNameAndAgeToUsers` (the string `NameAndAge` does not matter, you specify columns individually, however `Users` does matter because this will be the name of the table)

```
$ cargo loco g migration AddNameAndAgeToUsers name:string age:int
```

### Remove columns

* Name template: `Remove___From___`
* Example: `RemoveNameAndAgeFromUsers` (same note exists as in _add columns_)

```
$ cargo logo g migration RemoveNameAndAgeFromUsers name:string age:int
```

### Add references

* Name template: `Add___RefTo___`
* Example: `AddUserRefToPosts` (`User` does not matter, as you specify one or many references individually, `Posts` does matter as it will be the table name in the migration)

```
$ cargo loco g migration AddUserRefToPosts user:references
```

### Create a join table

* Name template: `CreateJoinTable___And___` (supported between 2 tables)
* Example: `CreateJoinTableUsersAndGroups`

```
$ cargo loco g migration CreateJoinTableUsersAndGroups count:int
```

You can also add some state columns regarding the relationship (such as `count` here).

### Create an empty migration

Use any descriptive name for a migration that does not fall into one of the above patterns to create an empty migration.

```
$ cargo loco g migration FixUsersTable
```

### Down Migrations

If you realize that you made a mistake, you can always undo the migration. This will undo the changes made by the migration (assuming that you added the appropriate code for `down` in the migration).
Expand Down Expand Up @@ -247,27 +308,11 @@ $ cargo loco generate model movies long_title:string added_by:references:users d
* reference added_by is in singular, the referenced model is a model and is plural: `added_by:references:users`
* column name in snake case: `long_title:string`

### Naming migrations

There are no rules for how to name migrations, but here's a few guidelines to keep your migration stack readable as a list of files:

* `<table>` - create a table, plural, `movies`
* `add_<table>_<field>` - add a column, `add_users_email`
* `index_<table>_<field>` - add an index, `index_users_email`
* `alter_` - change a schema, `alter_users`
* `delete_<table>_<field>` - remove a column, `delete_users_email`
* `data_fix_` - fix some data, using entity queries or raw SQL, `data_fix_users_timezone_issue_315`

Example:

```sh
$ cargo loco generate migration add_users_email
```

### Migration Definition

### Add or remove a column

Adding a column:
**Add a column**

```rust
manager
Expand All @@ -280,7 +325,7 @@ Adding a column:
.await
```

Dropping a column:
**Drop a column**

```rust
manager
Expand All @@ -293,8 +338,7 @@ Dropping a column:
.await
```

### Add index

**Add index**

You can copy some of this code for adding an index

Expand All @@ -310,8 +354,7 @@ You can copy some of this code for adding an index
.await;
```

### Create a data fix

**Create a data fix**

Creating a data fix in a migration is easy - just use SQL statements as you like:

Expand Down
Loading

0 comments on commit 481e1d0

Please sign in to comment.