首页 > 其他分享 >Let'sGoFurther - Chapter 8: Advanced CRUD Operations

Let'sGoFurther - Chapter 8: Advanced CRUD Operations

时间:2024-11-16 20:40:11浏览次数:1  
标签:Chapter Operations nil err movie app CRUD version input

 

 

 

 

 

var (
    ErrRecordNotFound = errors.New("record not found")
    ErrEditConflict   = errors.New("edit conflict")
)

 

func (m MovieModel) Update(movie *Movie) error {
    query := `UPDATE movie 
              SET title = $1, year = $2, runtime = $3, genres = $4, version = version + 1 
              WHERE id = $5 AND version = $6
              RETURNING version`

    args := []any{
        movie.Title,
        movie.Year,
        movie.Runtime,
        pq.Array(movie.Genres),
        movie.ID,
        movie.Version,  // Add the expected movie version.
    }

    err := m.DB.QueryRow(query, args...).Scan(&movie.Version)
    if err != nil {
        switch {
        case errors.Is(err, sql.ErrNoRows):
            return ErrEditConflict
        default:
            return err
        }
    }

    return nil
}

 

func (app *application) editConflictResponse(w http.ResponseWriter, r *http.Request) {
    message := "unable to update the record due to an edit conflict, please try again"
    app.errorResponse(w, r, http.StatusConflict, message)
}

 

func (app *application) updateMovieHandler(w http.ResponseWriter, r *http.Request) {
    id, err := app.readIDParam(r)
    if err != nil {
        app.notFoundResponse(w, r)
        return
    }

    movie, err := app.models.Movie.Get(id)
    if err != nil {
        switch {
        case errors.Is(err, data.ErrRecordNotFound):
            app.notFoundResponse(w, r)
        default:
            app.serverErrorResponse(w, r, err)
        }
        return
    }

    var input struct {
        Title   *string       `json:"title"`
        Year    *int32        `json:"year"`
        Runtime *data.Runtime `json:"runtime"`
        Genres  []string      `json:"genres"`
    }

    err = app.readJSON(w, r, &input)
    if err != nil {
        app.badRequestResponse(w, r, err)
        return
    }

    if input.Title != nil {
        movie.Title = *input.Title
    }
    if input.Year != nil {
        movie.Year = *input.Year
    }
    if input.Runtime != nil {
        movie.Runtime = *input.Runtime
    }
    if input.Genres != nil {
        movie.Genres = input.Genres  // Note that we don't need to dereference a slice.
    }
    

    v := validator.New()

    if data.ValidateMovie(v, movie); !v.Valid() {
        app.failedValidationResponse(w, r, v.Errors)
        return
    }

    err = app.models.Movie.Update(movie)
    if err != nil {
        switch {
        case errors.Is(err, data.ErrEditConflict):
            app.editConflictResponse(w, r)
        default:
            app.serverErrorResponse(w, r, err)
        }
        return
    }

    err = app.writeJSON(w, http.StatusOK, envelope{"movie": movie}, nil)
    if err != nil {
        app.serverErrorResponse(w, r, err)
    }
}

 

zzh@ZZHPC:~$ xargs -I % -P8 curl -X PATCH -d '{"runtime": "97 mins"}' "localhost:4000/v1/movies/4" < <(printf '%s\n' {1..8})
{
    "movie": {
        "id": 4,
        "title": "The Breakfast Club",
        "year": 1985,
        "runtime": "97 mins",
        "genres": [
            "drama"
        ],
        "version": 3
    }
}
{
    "movie": {
        "id": 4,
        "title": "The Breakfast Club",
        "year": 1985,
        "runtime": "97 mins",
        "genres": [
            "drama"
        ],
        "version": 4
    }
}
{
    "error": "unable to update the record due to an edit conflict, please try again"
{
}
    "error": "unable to update the record due to an edit conflict, please try again"
}
{
    "error": "unable to update the record due to an edit conflict, please try again"
}
{
    "movie": {
        "id": 4,
        "title": "The Breakfast Club",
        "year": 1985,
        "runtime": "97 mins",
        "genres": [
            "drama"
        ],
        "version": 5
    }
}
{
    "error": "unable to update the record due to an edit conflict, please try again"
}
{
    "movie": {
        "id": 4,
        "title": "The Breakfast Club",
        "year": 1985,
        "runtime": "97 mins",
        "genres": [
            "drama"
        ],
        "version": 6
    }
}

-P max-procs, --max-procs=max-procs
Run up to max-procs processes at a time; the default is 1. If max-procs is 0, xargs will run as many processes as possible at a time.

 

标签:Chapter,Operations,nil,err,movie,app,CRUD,version,input
From: https://www.cnblogs.com/zhangzhihui/p/18549794

相关文章

  • 运维开发之脚本语言(Script Language for Operations and Development)
     ......
  • SpringBoot整合Mybatis进行crud操作
    SpringBoot整合Mybatis进行crud操作一:创建数据表学生表createtables_stu(idintprimarykeyauto_increment,snamevarchar(255),ageint,sexchar(1),scoredouble(10,2),birthdaydate);教室表createtables_classroom(cidintprimarykey......
  • Let'sGoFurther - Chapter 6: SQL Migrations
      InstallingthemigratetoolTomanageSQLmigrationsinthisprojectwe’regoingtousethemigratecommand-line tool(whichitselfiswritteninGo).OnLinuxandWindows,theeasiestmethodistodownloadapre-builtbinaryandmove ittoalocat......
  • MySQL:CRUD
    MySQL表的增删改查(操作的是表中的记录)CRUD(增删改查)C-Create新增R-Retrieve检查,查询U-Update更新D-Delete删除新增(Create)语法:单行数据+全列插入 insertinto表名[字段一,字段二]values(值一,值二); 通过看表的结果,我们可以看出内容已经写好注:列和值的数据类型一定要......
  • Vue 3实现一个带有左侧导航菜单的页面。该页面包含一个类似的增删改查(CRUD)功能模块。
    效果图:实现步骤:项目结构我们将构建一个简单的Vue3项目,包含以下内容:左侧导航栏:用于切换不同页面或模块。右侧内容区域:用于展示不同模块的内容(如小组成员管理)。代码实现1.创建主页面组件App.vue首先,在App.vue中定义左侧导航栏和内容区域:<template><divid="app"......
  • GoFurther - Chapter 5: Database Setup and Configuration
     zzh@ZZHPC:/zdata/Github/greenlight$dockerpullpostgreszzh@ZZHPC:/zdata/Github/greenlight$dockerrun--namepostgres17-p5432:5432-ePOSTGRES_USER=root-ePOSTGRES_PASSWORD=root-dpostgres:latest zzh@ZZHPC:~$dockerexec-itpostgres17psql......
  • 【Chapter 4】Machine Learning Regression Case_Second hand Car Price Prediction-X
    文章目录一、XGBoostAlgorithm二、ComparisonofalgorithmimplementationbetweenPythoncodeandSentosa_DSMLcommunityedition(1)Datareadingandstatisticalanalysis(2)dataprocessing(三)Featureselectionandcorrelationanalysis(4)Samplepartit......
  • Spring boot HibernateJPA CRUD
    连接数据库和创建表1.pom安装<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency>......
  • 《TCP/IP网络编程》学习笔记 | Chapter 11:进程间通信
    《TCP/IP网络编程》学习笔记|Chapter11:进程间通信《TCP/IP网络编程》学习笔记|Chapter11:进程间通信进程间通信的基本概念通过管道实现进程间通信通过管道进行进程间双向通信运用进程间通信习题(1)什么是进程间通信?分别从概念和内存的角度进行说明。(2)进程间通信需要......
  • chapter17
    malloc.py参数中文版第一题问题1.首先运行flag-n10-H0-pBEST-s0来产生一些随机分配和释放。你能预测malloc()/free()会返回什么吗?你可以在每次请求后猜测空闲列表的状态吗?随着时间的推移,你对空闲列表有什么发现?空闲列表不会合并,导致外部碎片越来越多第二题......