Skip to content

Reading and Writing Record

Create

A new record can be inserted to database using a struct, map or set function. To insert a new record using a struct, simply pass the pointer to the instance as the only argment. Insertion using struct will update created_at and updated_at field if any.

Note

reltest.Repository will automatically sets any primary key value to be 1.

Inserting a record:

book := Book{
    Title:    "Rel for dummies",
    Category: "education",
    Author: Author{
        Name: "CZ2I28 Delta",
    },
}

// Insert directly using struct.
err := repo.Insert(ctx, &book)
repo.ExpectInsert()
repo.ExpectInsert().For(&Book{
    Title:    "Rel for dummies",
    Category: "education",
    Author: Author{
        Name: "CZ2I28 Delta",
    },
})
repo.ExpectInsert().ForType("main.Book")
repo.ExpectInsert().ForType("main.Book").Error(errors.New("oops"))

To inserts multiple records at once, use InsertAll:

books := []Book{
    {
        Title:    "Golang for dummies",
        Category: "education",
    },
    {
        Title:    "Rel for dummies",
        Category: "education",
    },
}

err := repo.InsertAll(ctx, &books)
repo.ExpectInsertAll().ForType("[]main.Book")

Read

REL provides a powerful API for querying record from database. To query a record, simply use the Find method, it accepts the returned result as the first argument, and the conditions for the rest arguments.

Retrieve a book with id 1:

var book Book
err := repo.Find(ctx, &book, rel.Eq("id", 1))
book := Book{
    Title:    "Rel for dummies",
    Category: "education",
}

repo.ExpectFind(rel.Eq("id", 1)).Result(book)

Retrieve a book with id 1 using syntactic sugar:

var book Book
err := repo.Find(ctx, &book, where.Eq("id", 1))
repo.ExpectFind(where.Eq("id", 1)).NotFound()

Querying multiple records using FindAll method:

var books []Book
err := repo.FindAll(ctx, &books,
    where.Like("title", "%dummies%").AndEq("category", "education"),
    rel.Limit(10),
)
books := []Book{
    {
        Title:    "Rel for dummies",
        Category: "education",
    },
}

repo.ExpectFindAll(
    where.Like("title", "%dummies%").AndEq("category", "education"),
    rel.Limit(10),
).Result(books)

Using chainable query api for a more complex query use case:

var books []Book
query := rel.Select("title", "category").Where(where.Eq("category", "education")).SortAsc("title")
err := repo.FindAll(ctx, &books, query)
books := []Book{
    {
        Title:    "Rel for dummies",
        Category: "education",
    },
}

query := rel.Select("title", "category").Where(where.Eq("category", "education")).SortAsc("title")
repo.ExpectFindAll(query).Result(books)

Update

Similar to create, updating a record in REL can also be done using struct, map or set function. Updating using struct will also update updated_at field if any.

An update using struct will cause all fields and association to be saved to database, regardless of whether it's been updated or not. Use rel.Map, rel.Set or rel.Changeset to update only specific fields.

Note

When updating belongs to association, it's recommended to not expose reference key ([other]_id) for updates directly from user, since there's no way to validate belongs to association using query.

Updating a record:

book.Title = "REL for dummies"
err := repo.Update(ctx, &book)
repo.ExpectUpdate().ForType("main.Book")

Updating records is custom query:

updatedCount, err := repo.UpdateAny(ctx, rel.From("books").Where(where.Lt("stock", 100)), rel.Set("discount", true))
repo.ExpectUpdateAny(rel.From("books").Where(where.Lt("stock", 100)), rel.Set("discount", true))

Delete

To delete a record in rel, simply pass the record to be deleted.

Note

REL will automatically apply soft-delete if DeletedAt *time.Time or Deleted bool field exists in a struct. DeletedAt needs to be pointer, otherwise it won't be able to save or store null value. To query soft-deleted records, use rel.Unscoped(true) when querying.

Deleting a record:

err := repo.Delete(ctx, &book)
repo.ExpectDelete().For(&book)

Deleting multiple record:

err := repo.DeleteAll(ctx, &books)
repo.ExpectDeleteAll().For(&books)

Deleting records using custom query:

deletedCount, err := repo.DeleteAny(ctx, rel.From("books").Where(where.Eq("id", 1)))
repo.ExpectDeleteAny(rel.From("books").Where(where.Eq("id", 1)))

Last update: 2024-12-19