Go基礎学習記録-Webアプリケーション作成-ブログ編集機能のモデルの再考


毎回私は自分の実践のコードをgithubの上でそしてすべて1つのtagを打って、后で使う学友に便利で、ここで私は下の分岐のコードで実践して分かち合います
https://github.com/durban89/typescript_demo.git
tag: 1.1.2

上记の文章【Go基础学习记录-Webアプリケーションの编集-ブログ编集完整更新机能】では、修正の过程で、Update関数とsqliteの関数が冲突するというヒントがあった.ヒントの内容は、この関数を再定义することを意味するだろう.今回は、更新するロジックを変更し、Modelを再定义するとともに、QueryOne関数も更新した.

第一歩、Modelの再定義


Modelを再定義するには、主に概念的にいくつかの論理を抽象化しています.例えば、クエリー文の最も基本的なwhere、select、更新中のupdate部分です.私はこの部分を小さなブロックとして処理します.処理コードロジックは以下のように、まずmodels/modelsを構築します.goファイル、内容は以下の通りです
package models

import (
    "fmt"
    "strings"
)

// Model  
type Model interface {
    QueryOne()
    Update()
}

// WhereCondition where 
type WhereCondition struct {
    Operator string
    Value    string
}

// WhereValues where 
type WhereValues map[string]WhereCondition

// UpdateValues update 
type UpdateValues map[string]string

// SelectValues select 
type SelectValues []string

// MergeWhere  where 
func (w WhereValues) MergeWhere() string {
    where := []string{}
    for k, v := range w {
        if v.Operator == "" {
            s := fmt.Sprintf("%s = %s", k, v.Value)
            where = append(where, s)
        } else {
            s := fmt.Sprintf("%s %s %s", k, v.Operator, v.Value)
            where = append(where, s)
        }
    }

    return strings.Join(where, " AND ")
}

// MergeUpdate  update 
func (u UpdateValues) MergeUpdate() string {
    update := []string{}
    for k, v := range u {
        s := fmt.Sprintf("%s = '%s'", k, v)
        update = append(update, s)
    }

    return strings.Join(update, ", ")
}

// MergeSelect   select 
func (s SelectValues) MergeSelect() string {
    return strings.Join(s, ", ")
}

これで少しはっきりしたと思います.そしてmodelsに置いておきます.goファイルは、ほとんどのモデルを表すためにこれらの方法があるはずです.
メソッドの変更が完了したらコントロールを変更する必要があります

ステップ2、Modelの変更


ここでは主にmodels/blogを修正する.goは,QueryOneとUpdateの2つの関数をそれぞれ修正し,修正後のコードは以下の通りである.
// QueryOne  
func (b *Blog) QueryOne(where WhereValues) (helpers.Page, error) {
    var selectString = SelectValues{
        "*",
    }.MergeSelect()

    var whereString = where.MergeWhere()

    sql := fmt.Sprintf("SELECT %s FROM %s WHERE %s LIMIT 0, 1", selectString, tableName, whereString)

    rows, err := Conn.Query(sql)

    var res = helpers.Page{}

    if err != nil {
        return res, err
    }

    for rows.Next() {
        var autokid int
        var title string
        err = rows.Scan(&autokid, &title)

        if err != nil {
            return res, err
        }

        p := helpers.Page{
            ID:    autokid,
            Title: title,
        }

        res = p
    }

    if res.ID == 0 {
        return res, errors.New(" ")
    }

    return res, nil
}

また、Update関数の内容は次のとおりです.
// Update  
func (b *Blog) Update(update UpdateValues, where WhereValues) (int64, error) {
    var updateString = update.MergeUpdate()
    var whereString = where.MergeWhere()

    sql := fmt.Sprintf("UPDATE %s SET %s WHERE %s", tableName, updateString, whereString)

    stmt, err := Conn.Prepare(sql)
    if err != nil {
        return 0, err
    }

    res, err := stmt.Exec()
    if err != nil {
        return 0, err
    }

    affect, err := res.RowsAffected()
    if err != nil {
        return 0, err
    }

    return affect, nil
}

ここではしばらくユニットテストを書いていません

ステップ3、コントローラの変更


Controllerの変更は主にarticleのArticleEdit関数を変更し、内容は以下の通りです.
// ArticleEdit  
func ArticleEdit(w http.ResponseWriter, r *http.Request) {
    id := r.URL.Query().Get("id")
    if id == "" {
        http.NotFound(w, r)
        return
    }

    where := models.WhereValues{
        "autokid": models.WhereCondition{
            Operator: "=",
            Value:    id,
        },
    }

    update := map[string]string{}

    if strings.ToLower(r.Method) == "get" {

        blogModel := &models.Blog{}

        p, err := blogModel.QueryOne(where)

        if err != nil {
            http.NotFound(w, r)
            return
        }

        crutime := time.Now().Unix()
        h := md5.New()
        io.WriteString(h, strconv.FormatInt(crutime, 10))
        token := fmt.Sprintf("%x", h.Sum(nil))

        p.Token = token
        helpers.RenderTemplate(w, "edit", &p)
    } else if strings.ToLower(r.Method) == "post" {
        title := r.FormValue("title")
        if title == "" {
            http.Redirect(w, r, fmt.Sprintf("/edit?id=%s", id), http.StatusFound)
            return
        }

        update["title"] = title

        blogModel := &models.Blog{}

        _, err := blogModel.Update(update, where)

        if err != nil {
            http.NotFound(w, r)
            return
        }

        http.Redirect(w, r, fmt.Sprintf("/edit?id=%s", id), http.StatusFound)
        return
    }

}

前の修正を経て、もっとgolangがプログラミング化されたと思います.
コードを再編集して実行し、すべて正常で、完全なコードを表示したい場合は、次のガイドにダウンロードしてください.
プロジェクト更新アドレス
https://github.com/durban89/typescript_demo.git
tag: 1.1.3