package model import ( "errors" "encoding/json" "database/sql" "fmt" ) type Step struct { Id string `json:"id"` Index string `json:"index"` Text string `json:"text"` Recipe string `json:"recipe"` } func (s Step) String() string { b, _ := json.MarshalIndent(s, "", " ") return string(b) } func (s *Step) Create(tx *sql.Tx) error { if s.Id != "" { return fmt.Errorf("Cannot create step if ID is given") } cmd := ` INSERT INTO steps ('index', text, recipe) VALUES (?, ?, ?) ` result, err := tx.Exec(cmd, s.Index, s.Text, s.Recipe) if err != nil { return err } id, err := result.LastInsertId() if err != nil { return err } s.Id = fmt.Sprint(id) return nil } func (s *Step) Read(tx *sql.Tx) error { cmd := ` SELECT "index", text, recipe FROM steps WHERE id = ? ` rows, err := tx.Query(cmd, s.Id) if err != nil { return err } defer rows.Close() if !rows.Next() { return sql.ErrNoRows } err = rows.Scan(&s.Index, &s.Text, &s.Recipe) if err != nil { return err } return nil } func (s *Step) Update(tx *sql.Tx) error { cmd := ` UPDATE steps SET index = ?, text = ?, recipe = ? WHERE id = ?` res, err := tx.Exec(cmd, s.Index, s.Text, s.Recipe, s.Id) if err != nil { return err } affected, err := res.RowsAffected() if err != nil { return err } if affected != 1 { return fmt.Errorf("Recipe update affected %d rows instead of 1", affected) } return nil } func (s *Step) Delete(tx *sql.Tx) error { cmd := ` DELETE FROM steps WHERE id = ? ` result, err := tx.Exec(cmd, s.Id) if err != nil { return err } rows, err := result.RowsAffected() if rows != 1 { return errors.New("Recipe deletion did not affect exactly one row") } return nil }