Skip to content

Instantly share code, notes, and snippets.

@brianfoshee
Created March 21, 2016 16:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianfoshee/cda33f14655bad77bf52 to your computer and use it in GitHub Desktop.
Save brianfoshee/cda33f14655bad77bf52 to your computer and use it in GitHub Desktop.
use SQL RETURNING to keep Go object up to date after actions. Lots of the actual file is omitted, the important stuff is here.
type Payment struct {
ID string
Amount uint64
Name string
Description string
Email string
Status PaymentStatus
StripeTokenID string
StripeChargeID string
CreatedAt time.Time
UpdatedAt time.Time
}
func (p *Payment) ChargeToken(tok string) error {
p.StripeTokenID = tok
defer p.Save()
chargeParams := &stripe.ChargeParams{
Amount: p.Amount,
Currency: "usd",
Desc: p.Description,
}
chargeParams.AddMeta("paymentID", p.ID)
chargeParams.Params.IdempotencyKey = p.ID
chargeParams.SetSource(p.StripeTokenID)
ch, err := charge.New(chargeParams)
if err != nil {
p.Status = PaymentStatusError
return err
}
p.StripeChargeID = ch.ID
p.Status = PaymentStatusPaid
return nil
}
func (p *Payment) Save() error {
if p.ID == "" {
return p.insert()
}
return p.update()
}
func (p *Payment) update() error {
q := `
UPDATE payment SET
name = $2,
description = $3,
amount = $4,
email = $5,
status = $6,
stripe_token_id = $7,
stripe_charge_id = $8
WHERE id = $1
RETURNING
name, description, amount, email, status, stripe_token_id,
stripe_charge_id, created_at, updated_at
`
err := db.QueryRow(q,
p.ID,
p.Name,
p.Description,
p.Amount,
p.Email,
p.Status,
p.StripeTokenID,
p.StripeChargeID,
).Scan(
&p.Name,
&p.Description,
&p.Amount,
&p.Email,
&p.Status,
&p.StripeTokenID,
&p.StripeChargeID,
&p.CreatedAt,
&p.UpdatedAt,
)
switch {
case err == sql.ErrNoRows:
return errors.New("payment: could not update")
case err != nil:
return err
}
return nil
}
func (p *Payment) insert() error {
q := `
INSERT INTO payment
(name, description, amount, email)
VALUES
($1, $2, $3, $4)
RETURNING
id, created_at, updated_at
`
err := db.QueryRow(q,
p.Name,
p.Description,
p.Amount,
p.Email,
).Scan(
&p.ID,
&p.CreatedAt,
&p.UpdatedAt,
)
switch {
case err == sql.ErrNoRows:
return errors.New("payment: insert did not return an object")
case err != nil:
return err
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment