↓↓クリックして頂けると励みになります。
【17 | カートの仕上げ】 << 【ホーム】 >> 【19 | Ajaxリクエスト送信】
Ajax(Asynchronous JavaScript and XML)は、クライアントサイドで非同期通信を可能にするための技術です。
Railsでは、Ajaxを使ってページの一部を非同期的に更新することができます。
具体的には、RailsではUJS(Unobtrusive JavaScript)と呼ばれる手法を用いて、Ajaxリクエストを簡単に扱うことができます。
これにより、ページ全体を再読み込みすることなく、特定の部分だけを更新することができます。
カートをAjaxスタイルにします。
トップページのサイドバーに現在のカートを配置します。
その後、ページ全体を再表示しなくてもサイドバー内のカートを更新できるようにします。
まずはカートをトップページに移動させます。
これには部分テンプレートを使います。
部分テンプレートとはビューの一部を専用のファイルに収めたものです。
別のテンプレートやコントローラから部分テンプレートを呼び出す(レンダリングする)ことができ、部分テンプレートは自身をレンダリングして結果を返します。
通常テンプレートの名前と区別するためファイルの検索時に部分テンプレートの名前の先頭に自動的にアンダーズコア(_)を追加します。
コントローラー
まずはmarketsコントローラの変更を行います。
「SampleCart/app/controllers/markets_controller.rb」ファイルを以下のように編集します。
「include CurrentCart」と「before_action :set_cart」の記述を追加しています。
記述追加 【SampleCart/app/controllers/markets_controller.rb】
class MarketsController < ApplicationController include CurrentCart before_action :set_cart def index @goods = Good.order(:title) end end
各商品の「カートに入れる」ボタンを押した時に、トップページにリダイレクトされるよう、line_itemsコントローラーを編集します。
「SampleCart/app/controllers/line_items_controller.rb」ファイルの32行目の記述を変更しています。
記述変更 【SampleCart/app/controllers/line_items_controller.rb】32行目
class LineItemsController < ApplicationController include CurrentCart before_action :set_cart, only: [:create] before_action :set_line_item, only: %i[ show edit update destroy ] # GET /line_items or /line_items.json def index @line_items = LineItem.all end # GET /line_items/1 or /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 or /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 markets_index_url, notice: "商品をカートに追加しました。" } format.json { render :show, status: :created, location: @line_item } else format.html { render :new, status: :unprocessable_entity } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end # PATCH/PUT /line_items/1 or /line_items/1.json def update respond_to do |format| if @line_item.update(line_item_params) format.html { redirect_to line_item_url(@line_item), notice: "Line item was successfully updated." } format.json { render :show, status: :ok, location: @line_item } else format.html { render :edit, status: :unprocessable_entity } format.json { render json: @line_item.errors, status: :unprocessable_entity } end end end # DELETE /line_items/1 or /line_items/1.json def destroy @line_item.destroy! respond_to do |format| format.html { redirect_to line_items_url, notice: "Line item was successfully destroyed." } 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) end end
ビュー
「SampleCart/app/views/carts/_cart.html.erb」ファイルの内容を以下の記述に編集します。
「SampleCart/app/views/carts/show.html.erb」ファイルの内容をほとんどコピーしただけですが、一部レイアウトの記述を変えています。
記述編集 【SampleCart/app/views/carts/_cart.html.erb】
<div class="container"> <div class="card"> <div class="card-body"> <div class="card-title h5 mb-4"><strong>現在のカート</strong></div> <% @cart.line_items.each do |item| %> <div class="card mb-2"> <div class="card-body"> <div><strong><%= item.good.title %></strong></div> <span class="badge bg-warning"><%= number_to_currency(item.good.price) %></span> × <span class="badge bg-primary"><%= item.quantity %>個</span> <div class="badge bg-danger w-100 mt-3">小計:<%= number_to_currency(item.total_price) %></div> </div> </div> <% end %> <div class="container mt-4"> <span class="badge bg-secondary">合計金額</span> <span class="badge bg-success fs-5"><%= number_to_currency(@cart.total_price) %></span> </div> <div class="mt-4"> <%= button_to 'カートを空にする', @cart, method: :delete, class: 'btn btn-outline-danger', data: { turbo: false }, form: { onSubmit: "return check()" } %> </div> </div> </div> </div> <script> function check(){ if(window.confirm('カートを空にしますか?')){ return true; } else{ window.alert('キャンセルされました'); return false; } } </script>
「SampleCart/app/views/carts/show.html.erb」ファイルを作成したレンダーファイルを読み込む内容に編集します。
記述編集 【SampleCart/app/views/carts/show.html.erb】
<%= render @cart %>
次にトップページの左にテンプレートを組み込みます。
「SampleCart/app/views/markets/index.html.erb」ファイルを以下のように編集します。
記述編集 【SampleCart/app/views/markets/index.html.erb】5行目
<div class="container mt-4"> <div class="row"> <!-- 右側(カート)--> <div class="col-md-4"> <div id="cart" class="carts"> <%= render @cart %> </div> </div> <!-- 左側(商品リスト) --> <div class="col-md-8"> <div class="row"> <% @goods.each do |good| %> <div class="col-md-4"> <div class="card"> <img src="<%= good.image_url %>" class="card-img-top"> <div class="card-body"> <h6 class="card-title"><strong><%= good.title %></strong></h6> <div class="badge bg-danger fs-6"> <%= good.price %>円 </div> <br/> <div class="badge bg-secondary"> <%= good.maker %> </div> <div class="badge bg-primary"> <%= good.category %> </div> <div class="mt-4"> <%= link_to "この商品の詳細", good, class: "btn btn-success" %> </div> <div class="mt-4"> <%= button_to 'カートに入れる', line_items_path(good_id: good ), class: "btn btn-warning" %> </div> </div> </div> </div> <% end %> </div> </div> </div> </div>
ブラウザでカートの表示と動作を確認してみます。
http://localhost:3000/
【17 | カートの仕上げ】 << 【ホーム】 >> 【19 | Ajaxリクエスト送信】
↓↓クリックして頂けると励みになります。