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)))