Railsで商品予約システムを開発しています。
巷のアプリとかでもよくある「この内容でよろしいですか?」みたいな確認画面を
newとcreateの間に挟みたいな・・・と思いつきました。
主なモデルは以下
ユーザー:user
商品:product
注文:order
先に、参考にさせていただいた記事
自分的にはconfirmアクションを作って間に噛ませるのが
わかりやすいかなと思い試しましたが、いまいちうまく行かなかったので、
上の記事で紹介されているように、newとcreateのみ使用しつつ
confirmを値として持たせる方法で実装しました。
もう、本当に上の記事に書いてある通りなのですが、まとめると
通常
new→
バリデーション→
バリデーション引っかかったらnewに戻る・クリアしたらcreate
今回
new→
バリデーション(ここで一工夫)→
newに戻ってくる(アクションはnewだけど確認用のviewを表示)→
「確定する」的なボタンが押されたらcreate
と言った感じで、バリデーションの機能をうまく使って
newとcreateのみでページ推移を実現させている感じです。
早速やってみる
model/order.rb
def check_confirming
errors.delete(:confirming)
self.confirming = errors.empty? ? '1' : ''
end
ちょっとここの記述がいまいち分からなかったけど、
他にバリデーションに引っかかった値がなければ(正常に登録されていれば)
confirmingの値を「1」に設定してね、と言う意味
次にコントローラー
controllers/orders_controller.rb
最初にcreateアクションが呼ばれた時点では
confirmingが存在しない=saveできないのでnewにrenderします。
しかしrenderでnewに戻ってきた時点ですでに
バリデーションを通過している=confirmingの値が1にセットされている
ので、2回目以降createが呼ばれた時はsaveされるようになっています
あとはビューで
最初にnewアクションが呼ばれた場合と、
confirmingが設置された状態でrenderで戻ってきた場合で
分岐すればOK
views/orders/new.html.haml
- if @order.confirming.blank?
//confirmingの値がない=最初にnewが呼ばれた時なので
普通にフォームをここに記述
確認用のテーブルをここに記述
confirmingの値がない場合 (最初のnewアクション)
最後まで入力して確認画面へ
(一旦createが呼ばれるが、confirmingが無いのでsaveされずnewに戻る)
newに戻ってくる
(バリデーションを経由しconfirmingが既にセットされている)
最終的にここでcreate
(今度はconfirmingの値を持っているので、適切にsaveされてDBに保存される)
と言う感じ。
新規作成のフォームも確認画面もどちらもnewアクションを使用していますが
confirmingを使用することで、表示するビューを分岐した上で
適切にページ推移が実行できるようになっています。