Editing a word uses the PUT method, which represents updating a resource.
Add Api
api/words/v1/words.go
type UpdateReq struct {
g.Meta `path:"words/{id}" method:"put" sm:"Update" tags:"Word"`
Id uint `json:"id" v:"required"`
Word string `json:"word" v:"required|length:1,100" dc:"Word"`
Definition string `json:"definition" v:"required|length:1,300" dc:"Word Definition"`
ExampleSentence string `json:"example_sentence" v:"required|length:1,300" dc:"Example Sentence"`
ChineseTranslation string `json:"chinese_translation" v:"required|length:1,300" dc:"Chinese Translation"`
Pronunciation string `json:"pronunciation" v:"required|length:1,100" dc:"Pronunciation"`
ProficiencyLevel uint `json:"proficiency_level" v:"required|between:1,5" dc:"Proficiency Level, 1 minimum, 5 maximum"`
}
type UpdateRes struct {
}
Implement Logic
During editing, we also need to check if the word is unique. The existing checkWord function is not sufficient, as it checks including itself, so we need to improve it:
- Add an
idfield; when theidis not0, use the combination ofidandwordfor judgment; - When
idis0, it represents a new addition, and onlywordis used for judgment.
internal/logic/words/words.go
package words
...
func (w *Words) Create(ctx context.Context, in *model.WordInput) error {
if err := w.checkWord(ctx, 0, in); err != nil {
return err
}
...
}
// checkWord does not check itself during an update
func (w *Words) checkWord(ctx context.Context, id uint, in *model.WordInput) error {
db := dao.Words.Ctx(ctx).Where("uid", in.Uid).Where("word", in.Word)
if id > 0 {
db = db.WhereNot("id", id)
}
count, err := db.Count()
if err != nil {
return err
}
if count > 0 {
return gerror.New("Word already exists")
}
return nil
}
Add the update logic:
internal/logic/words/words.go
package words
...
func (w *Words) Update(ctx context.Context, id uint, in *model.WordInput) error {
if err := w.checkWord(ctx, id, in); err != nil {
return err
}
db := dao.Words.Ctx(ctx).Where("uid", in.Uid).Data(do.Words{
Word: in.Word,
Definition: in.Definition,
ExampleSentence: in.ExampleSentence,
ChineseTranslation: in.ChineseTranslation,
Pronunciation: in.Pronunciation,
ProficiencyLevel: in.ProficiencyLevel,
}).Where("id", id)
if in.Uid > 0 {
db = db.Where("uid", in.Uid)
}
_, err := db.Update()
if err != nil {
return err
}
return nil
}
...
When Uid is greater than zero, the Uid condition must be added to the ORM chain to prevent unauthorized access, the same applies to subsequent query and delete actions.
Controller Calls Logic
internal/controller/words/words_v1_update.go
package words
import (
"context"
"star/internal/model"
"star/api/words/v1"
)
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
uid, err := c.users.GetUid(ctx)
if err != nil {
return nil, err
}
err = c.words.Update(ctx, req.Id, &model.WordInput{
Uid: uid,
Word: req.Word,
Definition: req.Definition,
ExampleSentence: req.ExampleSentence,
ChineseTranslation: req.ChineseTranslation,
Pronunciation: req.Pronunciation,
ProficiencyLevel: model.ProficiencyLevel(req.ProficiencyLevel),
})
return nil, err
}
API Test
$ curl -X PUT http://127.0.0.1:8000/v1/words/1 \
-H "Authorization: eyJhbGci...5U" \
-H "Content-Type: application/json" \
-d '{
"word": "example_update",
"definition": "A representative form or pattern.",
"example_sentence": "This is an example sentence.",
"chinese_translation": "例子",
"pronunciation": "ɪɡˈzɑːmp(ə)l",
"proficiency_level": 3
}'
{
"code": 0,
"message": "",
"data": null
}
Execute the command to check if the data has been updated correctly:
$ SELECT * FROM words;
| id | uid | word | definition | example_sentence | chinese_translation | pronunciation | proficiency_level | created_at | updated_at |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 1 | example_update | A representative form or pattern. | This is an example sentence. | 例子 | ɪɡˈzɑːmp(ə)l | 3 | 2024/11/12 15:38:50 | 2024/11/12 15:38:50 |