Model Design Rules
🎯 You should design your model first before providing any kind of service.
Briefly speeking, OJ Lab Service runs with models which mainly shows in JSON and mapped by GORM in database.
Usage of Struct Tag
To reduce the complexity of model usage, we should design as fewer models as possible, and the relationship between models should be well designed.
Fields Control
In different situations,
the model will carry different fields.
(
For example,
the password
field should be hidden in most cases,
but it should be shown when creating a new user.
Also,
to avoid security problems,
the password
field will not saved directly to database,
but a hashed_password
field will be saved instead.
)
Model Associations
The model may have associations with other models.
(
For example,
the user
model may have a role
field,
which is a list of role
model.
Also,
the role
model may have a user
field,
which is a list of user
model.
)
Usually, controlling these associations is very complex,
but we can rely on GORM to make it easier.
Solutions
Thanks to the ability of struct tag in JSON and GORM, we nearly don't need to write any model conversion codes.
The user struct is defined as below:
type User struct {
MetaFields
Account string `gorm:"primaryKey" json:"account"`
Name string `json:"name"`
Password *string `gorm:"-:all" json:"password,omitempty"`
HashedPassword string `gorm:"not null" json:"-"`
Roles []*Role `gorm:"many2many:user_roles;" json:"roles,omitempty"`
Email string `gorm:"unique" json:"email,omitempty"`
Mobile string `gorm:"unique" json:"mobile,omitempty"`
}
type Role struct {
Name string `gorm:"primaryKey" json:"name"`
Users []*User `gorm:"many2many:user_roles" json:"users,omitempty"`
}
You can try refering the following links to learn:
We don't get a very good JSON usage document for now. Simply search for 'go JSON struct tag' on the internet may help.
Model Naming
The struct and field naming will effect the table naming for GORM. Although GORM provides a way to customize table name, but it can be really confuse when struct convert to structs and got different table names.
So it will be better to keep the default naming rules and make table and struct names the same. Then we will get fewer struct being defined, and less conversion which may cause confusion.
Another thing which may cause confusion is when you are trying to define model like Tag
, Form
etc.
These names only describe the model itself,
but do not show any relationship between models,
also there are some other models with the same name (like there might be many Tag
models).
So it will be better to add some prefix to the model name,
but don't use the parent model name as prefix (like UserTag
or ProblemTag
).
Try to be more specific for the real usage (like AlgorithmTag
).