<<前 [TOP] 次>>
ショッピングカートをAjaxスタイルにします。
ショッピングカート用のページを新たに開くのではなく、カタログページのサイドバーに現在のカートを配置することにします。
その後でページ全体を再表示しなくてもサイドバー内のカートを更新できるようにします。
まずはカートを専用ページからサイドバーに移動させます。
これには部分テンプレートを使います。
部分テンプレートとはビューの一部を専用のショッピングカートをAjaxスタイルにします。
ショッピングカート用のページを新たに開くのではなく、カタログページのサイドバーに現在のカートを配置することにします。
その後でページ全体を再表示しなくてもサイドバー内のカートを更新できるようにします。
まずはカートを専用ページからサイドバーに移動させます。
これには部分テンプレートを使います。
部分テンプレートとはビューの一部を専用のファイルに収めたものです。
別のテンプレートやコントローラから部分テンプレートを呼び出す(レンダリングする)ことができ、部分テンプレートは自身をレンダリングして結果を返します。
メソッドのように部分テンプレートにパラメータを渡すこともできます。
これにより同じ部分テンプレートで異なるレンダリング結果を得ることもできます。
「C:\Rails6\work\shop\app\views\carts」フォルダの「show.html.erb」ファイルを以下のように編集します。
【C:\Rails6\work\shop\app\views\carts\show.html.erb】
<article> <% if notice %> <aside id="notice"><%= notice %></aside> <% end %> <h2>カートの内容</h2> <table> <%= render(@cart.line_tems) %> <tfoot> <tr> <th colspan="2">合計:</th> <td class="price"><%= number_to_currency(@cart.total_price) %></td> </tr> </tfoot> </table> <%= button_to 'カートを空にする', @cart, method: :delete, data: { confirm: '本当によろしいですか?' } %> </article>
「render()」メソッドは渡されたコレクションに対する繰り返し処理を行います。
部分テンプレートはそれ自体独立した1つのテンプレートファイルです。
デフォルトではレンダリング対象のオブジェクトと同じディレクトリに配置し、テーブル名と同じ名前にします。
通常テンプレートの名前と区別するためファイルの検索時に部分テンプレートの名前の先頭に自動的にアンダーズコア(_)を追加します。
「C:\Rails6\work\shop\app\views\line_items」フォルダ内にファイルを「_line_item.html.erb」という名前で新規作成します。
【C:\Rails6\work\shop\app\views\line_items\_line_item.html.erb】
<tr> <td><%= line_item.good.title %></td> <td class="quantity"><%= line_item.quantity %></td> <td class="price"><%= number_to_currency(line_item.total_price) %></td> </tr>
部分テンプレートの内部ではテンプレート名と同じ名前の変数を使って現在のオブジェクトを参照できます。
この部分テンプレートは「lineitem」という名前なので、その中では「line_item」という変数を使えます。
LineItemに部分テンプレートを使ったのでカートでも同じことをします。
まず「_cart.html.erb」テンプレートを作成し、@cartではなくcartを使います。
「C:\Rails6\work\shop\app\views\carts」フォルダ内にファイル「_cart.html.erb」を新規作成します。
内容は「C:\Rails6\work\shop\app\views\carts\show.html.erb」ファイルとほぼ同じですが「<%= render(cart.line_items) %>」の記述を追加しています。
【C:\Rails6\work\shop\app\views\carts\_cart.html.erb】
<article> <% if notice %> <aside id="notice"><%= notice %></aside> <% end %> <h2>カートの内容</h2> <table> <tr> <th>商品名</th> <th>数量</th> <th>価格</th> </tr> <%= render(cart.line_items) %> <tfoot> <tr> <th colspan="2">合計:</th> <td class="price"><%= number_to_currency(@cart.total_price) %></td> </tr> </tfoot> </table> <%= button_to 'カートを空にする', @cart, method: :delete, data: { confirm: '本当によろしいですか?' } %> </article>
このままでは「show.html.erb」と「_cart.html.erb」の全く同じ内容のファイルができてしまうので元のテンプレートを部分テンプレートをレンダリングするコードに置き換えます。
「C:\Rails6\work\shop\app\views\carts\show.html.erb」ファイルを以下のように編集します。
【C:\Rails6\work\shop\app\views\carts\show.html.erb】
<%= render @cart %>
次にアプリケーションのレイアウトを変更してサイドバーに新しいテンプレートを組み込みます。
「C:\Rails6\work\shop\app\views\layouts」フォルダにある「application.html.erb」ファイルを以下のように編集します。
サイドバーの部分に「
【C:\Rails6\work\shop\app\views\layouts\application.html.erb】
<!DOCTYPE html> <html> <head> <title>Railsはじめてマート オンラインストア</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <body> <header class="main"> <%= image_tag 'logo.png', alt: 'Railsはじめてマート', width: 80 %> </header> <section class="content"> <nav class="side_nav"> <div id="cart" class="carts"> <%= render @cart %> </div> <ul> <li><a href="/">ホーム</a></li> <li><a href="/questions">質問</a></li> <li><a href="/news">ニュース</a></li> <li><a href="/contact">問い合わせ</a></li> </ul> </nav> <main class='<%= controller.controller_name %>'> <%= yield %> </main> </section> </body> </html>
コントローラの変更を行います。
「C:\Rails6\work\shop\app\controllers」フォルダにある「market_controller.rb」ファイルを以下のように編集します。
「include CurrentCart」と「before_action :set_cart」の記述を追加しています。
【C:\Rails6\work\shop\app\controllers\market_controller.rb】
class MarketController < ApplicationController include CurrentCart before_action :set_cart def index @goods = Good.order(:title) end end
最後にスタイルシートを変更します。
まずは「C:\Rails6\work\shop\app\assets\stylesheets\application.css」の編集です。
以下の記述を追加します。
【C:\Rails6\work\shop\app\assets\stylesheets\application.css】
article { padding: 1.414em; background: white; border-radius: 1.5em; margin: 1.414em; font-size: smaller; }
「カートに入れる」ボタンの動作を変更します。
カート用のページは表示しないようにしてメインのインデックスページを更新するだけにします。
「C:\Rails6\work\shop\app\controllers」フォルダにある「line_items_controller.rb」ファイルを以下のように編集します。
「create()」メソッドの「format.html { redirect_to market_index_url }」の部分を変更するだけです。
【C:\Rails6\work\shop\app\controllers\line_items_controller.rb】
class LineItemsController < ApplicationController include CurrentCart before_action :set_cart, only: [:create] before_action :set_line_item, only: [:show, :edit, :update, :destroy] # GET /line_items # GET /line_items.json def index @line_items = LineItem.all end # GET /line_items/1 # GET /line_items/1.json def show end # GET /line_items/new def new @line_item = LineItem.new end # GET /line_items/1/edit def edit end # POST /line_items # POST /line_items.json def create good = Good.find(params[:good_id]) @line_item = @cart.add_good(good) respond_to do |format| if @line_item.save format.html { redirect_to market_index_url } format.json { render :show, status: :created, location: @line_item } else format.html { render :new } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end # PATCH/PUT /line_items/1 # PATCH/PUT /line_items/1.json def update respond_to do |format| if @line_item.update(line_item_params) format.html { redirect_to @line_item, notice: '品目が更新されました。' } format.json { render :show, status: :ok, location: @line_item } else format.html { render :edit } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end # DELETE /line_items/1 # DELETE /line_items/1.json def destroy @line_item.destroy respond_to do |format| format.html { redirect_to line_items_url, notice: '品目を破棄しました。' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_line_item @line_item = LineItem.find(params[:id]) end # Only allow a list of trusted parameters through. def line_item_params params.require(:line_item).permit(:good_id, :cart_id) end end
「http://localhost:3000/]にアクセスしてブラウザの表示を確認してみます。
↓↓クリックして頂けると励みになります。