このエントリはPlay frameworkひとりアドベントカレンダーの21日目です。
今日はいよいよ /buy を実装します。
今日も昨日までと同じ流れでいきましょう。
- 元コードを見てcontrollerのinput/outputとviewのinput/outputを確認
- modelを作る
- viewを作る
- controllerを作る(TODOでよい)
- 表示確認
- controllerを作りこむ
元コード
post '/buy' => sub {
my ($self, $c) = @_;
my $variation_id = $c->req->param('variation_id');
my $member_id = $c->req->param('member_id');
my $txn = $self->dbh->txn_scope();
$self->dbh->query(
'INSERT INTO order_request (member_id) VALUES (?)',
$member_id,
);
my $order_id = $self->dbh->last_insert_id;
my $rows = $self->dbh->query(
'UPDATE stock SET order_id = ? WHERE variation_id = ? AND order_id IS NULL ORDER BY RAND() LIMIT 1',
$order_id, $variation_id,
);
if ($rows > 0) {
my $seat_id = $self->dbh->select_one(
'SELECT seat_id FROM stock WHERE order_id = ? LIMIT 1',
$order_id,
);
$txn->commit;
$c->render('complete.tx', { seat_id => $seat_id, member_id => $member_id });
} else {
$txn->rollback;
$c->render('soldout.tx');
}
};
model, viewは淡々と作ればokです。
controllerのポイントは2点。
- POSTでデータを受け取る
- トランザクションを使った更新処理
POSTでデータを受け取る
request().body().asFormUrlEncoded()
を使いましょう。
素朴でrawな感じですが、これでいいにしましょう。
トランザクションを使った更新処理
Ebean
を使います。
Ebean.beginTransaction()
, Ebean.commitTransaction()
, Ebean.rollbackTransaction()
, Ebean.endTransaction()
でトランザクションしましょう。
public static Result buy() {
Map requestBody = request().body().asFormUrlEncoded();
String variationId = requestBody.containsKey("variation_id") ? requestBody
.get("variation_id")[0] : "";
String memberId = requestBody.containsKey("member_id") ? requestBody
.get("member_id")[0] : "";
Ebean.beginTransaction();
OrderRequest orderRequest = new OrderRequest();
orderRequest.memberId = memberId;
orderRequest.save();
Stock stock = Stock.find.where().eq("variation_id", variationId)
.isNull("order_id").orderBy("RAND()").findList().get(0);
stock.orderId = orderRequest.id;
stock.save();
try {
Ebean.commitTransaction();
Ebean.endTransaction();
} catch (Exception e) {
Ebean.rollbackTransaction();
Ebean.endTransaction();
return ok(views.html.soldout.render());
}
String seatId = Stock.find.where()
.eq("order_id", orderRequest.id.toString()).findList().get(0).seatId;
return ok(views.html.buy.render(seatId, memberId));
}
できました?これでひと通り動作できるようになりました。
明日は画面左側の recent_sold
を実装しましょう。