商品のリストは大方できたので、次はカートの作成にとりかかりましょう。
rails generate scaffold Cart
でカートを作成します。
scaffoldはView、Controller、Model(+ルーティング)をまとめた雛形を作成してくれるRailsの機能で、全機能が必要な場合は非常に便利な機能です。ここからはこちらも適宜使っていきます。
モデルを作成したのでmigrateもしましょう
rails db:migrate
カートは、とりあえずのところ、セッションで管理します。セッションが始まった時にカートを作成するmoduleを作成します。
app/controllers/concerns/current_cart.rbを作り
module CurrentCart private def set_cart @cart = Cart.find(session[:cart_id]) rescue ActiveRecord::RecordNotFound @cart = Cart.create session[:cart_id] = @cart.id end end
ターミナルでscaffoldのログを確認し、できたファイルの構成と中身を確認しましょう。
また、rescueについて調べ、CurrentCartで何が起こっているか理解しましょう。
さて、これでカートはできましたが、どのようにしてカートとその中のいくつかの商品を管理したらよいでしょうか。
カートに商品のカラムを作ると商品の数だけカラムが必要ですし、品目をどんどん足していくにしても取り出すときにまた分割しなければなりません。
ここでは、 LineItem(項目)というモデルを作り、カートは個々のカートの識別に使い、中身はカートに紐付けられたLineItemで管理するのがよいでしょう。
railsには has_one, has_many, belongs_to といったモデルの依存関係を作る関数が用意されていますので、これらを用いて実現できます。
まず、LineItemを作りましょう
rails generate scaffold LineItem item:references cart:belongs_to
今度はまた新たな宣言が加わっています。
line_item.rb を見てみましょう。 belongs_to という設定が追加されているかと思います。
これらは、データベースではFOREIGN KEYといって紐付けられた他のテーブルの内容を参照できる機能です。
確認したら、migrateしましょう。
先ほどの set_cart と LineItemを作るコードを line_items_controller.rb に下記を加えます。
include CurrentCart before_action :set_cart, only: [:create] before_action :set_line_item, only: [:show, :edit, :update, :destroy] ... def create item = Item.find(params[:item_id]) @line_item = @cart.line_items.build() ... private def set_line_item @line_item = LineItem.find(params[:id]) end ...
今度はカート側にLineItemとの関係を書き加えます。
カートは複数のLineItemを持つことができ、Cartが削除された際には中身のLineItemも削除されるべきです。
cart.rb
has_many :line_items, dependent: :destroy
また、ItemとLineItemの関係も必要です。
・「カートに追加する」ボタンを配置しましょう(現状はカート用ページに飛んで構いません)。
・Itemは複数のLineItemを持ちうる
・LineItemが存在している間は該当のItemを削除できない(before_[action_name] を用います)
上記二つを実装し、
・「LineItemが存在しているItemを削除しようとすると失敗する」テストを書いてください。
ここまででカートに関するロジックは揃ってきました。実際にそれを使っていきます。
まず、カートにジャンプする基となるページは「編集」や「削除」などのないユーザーページから行うのでそれをStoreとして作ります。
rails generate controller Store index
Storeにモデルは必要ないのでcontrollerだけ作ります。
・Storeのインデックスページをサイトのルートページに設定してください。
・ボタンが押された時に、しっかりline_itemが作られるか確認するテストをline_items_controller_test.rbに追加しましょう。
・カートが期待通りの動作をすることを確認しましょう。
・カートに追加された際の表示メッセージを変更しましょう。
・いくつか実際に追加されたら、関連モデルの内容をどのような表現で参照できるかrails console
から確認しましょう。
・セッションにカウンターを追加し、2回目以降のアクセスの場合、「Hi, again!」と表示されるようにしてください。