Skip to content

Commit

Permalink
feat: add example (#36)
Browse files Browse the repository at this point in the history
* feat: add example

* feat: add more comment

---------

Co-authored-by: Eyo Chen <[email protected]>
  • Loading branch information
eyo-chen and Eyo Chen authored Aug 25, 2024
1 parent 4d37319 commit 7a00af5
Show file tree
Hide file tree
Showing 7 changed files with 410 additions and 18 deletions.
119 changes: 119 additions & 0 deletions examples/association_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Package example_test provides examples demonstrating the usage of the gofacto library.
//
// These examples are for demonstration purposes and are not meant to be run directly.
// They serve as reference implementations to illustrate various features and use cases of gofacto.
// In a real-world scenario, you would need to provide actual database connections and adjust the code accordingly.
package example_test

import (
"context"
"fmt"

"github.com/eyo-chen/gofacto"
"github.com/eyo-chen/gofacto/db/mysqlf"
"github.com/eyo-chen/gofacto/typeconv"
)

// order has a foreign key field `CustomerID` to customer
type order struct {
ID int
CustomerID int `gofacto:"struct:customer"` // set the correct tag
Amount int
}

// Example_association demonstrates how to build associations value in an easy way.
// First, we need to set the correct tag on the foreign key field to tell gofacto which struct to associate with.
// Then, we can use `WithOne` or `WithMany` to create the association value and set the connection between the two structs.
func Example_association() {
// init a oreder factory
f := gofacto.New(order{}).
WithDB(mysqlf.NewConfig(nil)) // you should pass db connection

// build one order with one customer
customer1 := customer{}
order1, err := f.Build(ctx).
WithOne(&customer1). // must pass the struct pointer to WithOne or WithMany
Insert()
if err != nil {
panic(err)
}
fmt.Println(order1) // {ID: 1, CustomerID: 1, Amount: {{non-zero value}}}
fmt.Println(customer1) // {ID: 1, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
fmt.Println(order1.CustomerID == customer1.ID) // true

// build two orders with two customers
customer2 := customer{}
customer3 := customer{}
orders1, err := f.BuildList(ctx, 2).
WithMany([]interface{}{&customer2, &customer3}). // must pass the struct pointer to WithOne or WithMany
Insert()
if err != nil {
panic(err)
}
fmt.Println(orders1[0]) // {ID: 2, CustomerID: 2, Amount: {{non-zero value}}}
fmt.Println(orders1[1]) // {ID: 3, CustomerID: 3, Amount: {{non-zero value}}}
fmt.Println(customer2) // {ID: 2, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
fmt.Println(customer3) // {ID: 3, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
fmt.Println(orders1[0].CustomerID == customer2.ID) // true
fmt.Println(orders1[1].CustomerID == customer3.ID) // true

// build two orders with one customer
customer4 := customer{}
orders2, err := f.BuildList(ctx, 2).
WithOne(&customer4). // must pass the struct pointer to WithOne or WithMany
Insert()
if err != nil {
panic(err)
}
fmt.Println(orders2[0]) // {ID: 4, CustomerID: 4, Amount: {{non-zero value}}}
fmt.Println(orders2[1]) // {ID: 5, CustomerID: 4, Amount: {{non-zero value}}}
fmt.Println(customer4) // {ID: 4, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
fmt.Println(orders2[0].CustomerID == customer4.ID) // true
fmt.Println(orders2[1].CustomerID == customer4.ID) // true
}

// InsertOrders demonstrates how to use the functionality of `typeconv` package to simplify the code.
// In some cases, we might want to wrap the insert logic into a function.
// In this case, we define the `InsertOrders` function to insert `n` orders with `n` customers.
func InsertOrders(ctx context.Context, f *gofacto.Factory[order], n int) ([]order, []customer, error) {
// use `ToAnysWithOW` to generate `n` customers with any type
// The first parameter is the number of customers to generate
// The second parameter is the value to override the default value(we pass nil because we don't want to override the default value)
customersAny := typeconv.ToAnysWithOW[customer](n, nil)

orders, err := f.BuildList(ctx, n).
WithMany(customersAny).
Insert()
if err != nil {
return nil, nil, err
}

// convert the `[]any` to `[]customer` using `ToT`
customers := typeconv.ToT[customer](customersAny)

return orders, customers, nil
}

// Without the `typeconv` package, we would need to manually convert the `[]any` to `[]customer` using `ToT`
func InsertOrdersWithoutTypeconv(ctx context.Context, f *gofacto.Factory[order], n int) ([]order, []customer, error) {
// manually create `n` customers with any type
customersAny := make([]interface{}, n)
for i := 0; i < n; i++ {
customersAny[i] = &customer{}
}

orders, err := f.BuildList(ctx, n).
WithMany(customersAny).
Insert()
if err != nil {
return nil, nil, err
}

// manually convert the `[]any` to `[]customer`
customers := make([]customer, n)
for i := 0; i < n; i++ {
customers[i] = *customersAny[i].(*customer)
}

return orders, customers, nil
}
56 changes: 56 additions & 0 deletions examples/basic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Package example_test provides examples demonstrating the usage of the gofacto library.
//
// These examples are for demonstration purposes and are not meant to be run directly.
// They serve as reference implementations to illustrate various features and use cases of gofacto.
// In a real-world scenario, you would need to provide actual database connections and adjust the code accordingly.
package example_test

import (
"context"
"fmt"

"github.com/eyo-chen/gofacto"
"github.com/eyo-chen/gofacto/db/mysqlf"
)

var (
ctx = context.Background()
)

// Gender is a custom defined type
type gender string

const (
genderMale gender = "male"
genderFemale gender = "female"
)

type customer struct {
ID int
Gender gender
Name string
Age int
}

// Example_basic demonstrates the most basic usage of gofacto
// when we didn't provide any configuration(except db connection), gofacto will generate non-zero value for all fields
func Example_basic() {
f := gofacto.New(customer{}).
WithDB(mysqlf.NewConfig(nil)) // you should pass db connection

// build and insert one data
customer, err := f.Build(ctx).Insert()
if err != nil {
panic(err)
}
fmt.Println(customer) // {ID: 1, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
// Note that because Gender is a custom defined type, gofacto will ignore it, and leave it as zero value.

// build and insert multiple data
customers, err := f.BuildList(ctx, 2).Insert()
if err != nil {
panic(err)
}
fmt.Println(customers[0]) // {ID: 2, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
fmt.Println(customers[1]) // {ID: 3, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
}
45 changes: 45 additions & 0 deletions examples/blueprint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Package example_test provides examples demonstrating the usage of the gofacto library.
//
// These examples are for demonstration purposes and are not meant to be run directly.
// They serve as reference implementations to illustrate various features and use cases of gofacto.
// In a real-world scenario, you would need to provide actual database connections and adjust the code accordingly.
package example_test

import (
"fmt"

"github.com/eyo-chen/gofacto"
"github.com/eyo-chen/gofacto/db/mysqlf"
)

// Example_blueprint demonstrates how to use blueprint to generate data.
// When blueprint is provided, gofacto will first use the blueprint to generate data,
// then it will generate non-zero value for the rest of the fields which are not specified in the blueprint
func Example_blueprint() {
f := gofacto.New(customer{}).
WithBlueprint(blueprint). // set the blueprint function
WithDB(mysqlf.NewConfig(nil)) // you should pass db connection

customer, err := f.Build(ctx).Insert()
if err != nil {
panic(err)
}
fmt.Println(customer) // {ID: 1, Gender: "male", Name: "Bob", Age: 10}

customers, err := f.BuildList(ctx, 2).Insert()
if err != nil {
panic(err)
}
fmt.Println(customers[0]) // {ID: 2, Gender: "male", Name: "Bob", Age: 20}
fmt.Println(customers[1]) // {ID: 3, Gender: "male", Name: "Bob", Age: 30}
}

// Define a blueprint function with the following signature:
// type blueprintFunc[T any] func(i int) T
func blueprint(i int) customer {
return customer{
Name: "Bob",
Gender: genderMale,
Age: i * 10,
}
}
56 changes: 56 additions & 0 deletions examples/overwrite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Package example_test provides examples demonstrating the usage of the gofacto library.
//
// These examples are for demonstration purposes and are not meant to be run directly.
// They serve as reference implementations to illustrate various features and use cases of gofacto.
// In a real-world scenario, you would need to provide actual database connections and adjust the code accordingly.
package example_test

import (
"fmt"

"github.com/eyo-chen/gofacto"
"github.com/eyo-chen/gofacto/db/mysqlf"
)

// Example_overwrite demonstrates how to overwrite specific fields
func Example_overwrite() {
f := gofacto.New(customer{}).
WithDB(mysqlf.NewConfig(nil)) // you should pass db connection

// build one data, and overwrite the Name field
customer1, err := f.Build(ctx).Overwrite(customer{Name: "Alice"}).Insert()
if err != nil {
panic(err)
}
fmt.Println(customer1) // {ID: 1, Gender: "", Name: "Alice", Age: {{non-zero value}}}
// Note that because Gender is a custom defined type, gofacto will ignore it, and leave it as zero value.

// build two data, and overwrite the Gender and Name fields respectively
customers, err := f.BuildList(ctx, 2).
Overwrites(customer{Gender: genderMale, Name: "Alice"}, customer{Gender: genderFemale, Name: "Mag"}).
Insert()
if err != nil {
panic(err)
}
fmt.Println(customers[0]) // {ID: 2, Gender: "male", Name: "Alice", Age: {{non-zero value}}}
fmt.Println(customers[1]) // {ID: 3, Gender: "female", Name: "Mag", Age: {{non-zero value}}}

// build two data, and overwrite all the data list with the same value
customers1, err := f.BuildList(ctx, 2).
Overwrite(customer{Age: 10}).
Insert()
if err != nil {
panic(err)
}
fmt.Println(customers1[0]) // {ID: 4, Gender: "", Name: {{non-zero value}}, Age: 10}
fmt.Println(customers1[1]) // {ID: 5, Gender: "", Name: {{non-zero value}}, Age: 10}

// Note that we can't overwrite with zero value
// use `SetZero` or `SetTrait` to set zero value
customer2, err := f.Build(ctx).Overwrite(customer{Age: 0}).Insert()
if err != nil {
panic(err)
}
fmt.Println(customer2) // {ID: 4, Gender: "", Name: {{non-zero value}}, Age: {{non-zero value}}}
// Age is still a non-zero value
}
72 changes: 72 additions & 0 deletions examples/settrait_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Package example_test provides examples demonstrating the usage of the gofacto library.
//
// These examples are for demonstration purposes and are not meant to be run directly.
// They serve as reference implementations to illustrate various features and use cases of gofacto.
// In a real-world scenario, you would need to provide actual database connections and adjust the code accordingly.
package example_test

import (
"fmt"

"github.com/eyo-chen/gofacto"
"github.com/eyo-chen/gofacto/db/mysqlf"
)

// Example_settrait demonstrates how to use trait function to customize the data.
// We first define a trait function, then use `WithTrait` to register the trait function with a key,
// finally, use `SetTrait` to invoke the trait function.
func Example_settrait() {
f := gofacto.New(customer{}).
WithTrait("toMale", updateToMale). // set the trait function with key
WithTrait("toFemale", updateToFemale). // set the trait function with key
WithTrait("ageZero", updateAgeToZero). // set the trait function with key
WithDB(mysqlf.NewConfig(nil)) // you should pass db connection

// build one data, and invoke the trait function with key "toMale"
customer1, err := f.Build(ctx).SetTrait("toMale").Insert()
if err != nil {
panic(err)
}
fmt.Println(customer1) // {ID: 1, Gender: "male", Name: {{non-zero value}, Age: {{non-zero value}}}

// build two data, and invoke the trait function with key "toMale" and "toFemale" respectively
customers, err := f.BuildList(ctx, 2).SetTraits("toMale", "toFemale").Insert()
if err != nil {
panic(err)
}
fmt.Println(customers[0]) // {ID: 2, Gender: "male", Name: {{non-zero value}, Age: {{non-zero value}}}
fmt.Println(customers[1]) // {ID: 3, Gender: "female", Name: {{non-zero value}, Age: {{non-zero value}}}

// build two data, and invoke the trait function with key "toMale" on all the data list
customers1, err := f.BuildList(ctx, 2).SetTrait("toMale").Insert()
if err != nil {
panic(err)
}
fmt.Println(customers1[0]) // {ID: 4, Gender: "male", Name: {{non-zero value}, Age: {{non-zero value}}}
fmt.Println(customers1[1]) // {ID: 5, Gender: "male", Name: {{non-zero value}, Age: {{non-zero value}}}

// it's also possible to set zero value
customer2, err := f.Build(ctx).SetTrait("ageZero").Insert()
if err != nil {
panic(err)
}
fmt.Println(customer2) // {ID: 6, Gender: "", Name: {{non-zero value}}, Age: 0}
}

// define a trait function to update the value
func updateToMale(c *customer) {
c.Gender = genderMale
// more update logic can be added here
}

// define a trait function to update the value
func updateToFemale(c *customer) {
c.Gender = genderFemale
// more update logic can be added here
}

// define a trait function to update the value
func updateAgeToZero(c *customer) {
c.Age = 0
// more update logic can be added here
}
36 changes: 36 additions & 0 deletions examples/setzero_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Package example_test provides examples demonstrating the usage of the gofacto library.
//
// These examples are for demonstration purposes and are not meant to be run directly.
// They serve as reference implementations to illustrate various features and use cases of gofacto.
// In a real-world scenario, you would need to provide actual database connections and adjust the code accordingly.
package example_test

import (
"fmt"

"github.com/eyo-chen/gofacto"
"github.com/eyo-chen/gofacto/db/mysqlf"
)

// Example_setzero demonstrates how to explicitly set zero value on the specified fields.
func Example_setzero() {
f := gofacto.New(customer{}).
WithDB(mysqlf.NewConfig(nil)) // you should pass db connection

// build one data, and set zero value on the specified fields
customer, err := f.Build(ctx).SetZero("Age", "Name").Insert()
if err != nil {
panic(err)
}
fmt.Println(customer) // {ID: 1, Gender: "", Name: "", Age: 0}
// Note that because Gender is a custom defined type, gofacto will ignore it, and leave it as zero value..

// build two data, and set zero value on the specified fields
// the first parameter is the index of the list
// the second parameter is the field name that you want to set zero value on
customers, err := f.BuildList(ctx, 2).SetZero(0, "Age").SetZero(1, "Age", "Name").Insert()
if err != nil {
panic(err)
}
fmt.Println(customers) // [{ID: 2, Gender: "", Name: {{non-zero value}}, Age: 0}, {ID: 3, Gender: "", Name: "", Age: 0}]
}
Loading

0 comments on commit 7a00af5

Please sign in to comment.