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
id
field; when theid
is not0
, use the combination ofid
andword
for judgment; - When
id
is0
, it represents a new addition, and onlyword
is used for judgment.
internal/logic/words/words.go
package words
...
func Create(ctx context.Context, in *model.WordInput) error {
if err := checkWord(ctx, 0, in); err != nil {
return err
}
...
}
// checkWord does not check itself during an update
func 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 Update(ctx context.Context, id uint, in *model.WordInput) error {
if err := 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/logic/users"
"star/internal/logic/words"
"star/internal/model"
"star/api/words/v1"
)
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
uid, err := users.GetUid(ctx)
if err != nil {
return nil, err
}
err = 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 |