@seiyarick (seiya)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

cart_itemが入っていなければ次のページへ遷移できなくする方法

解決したいこと

管理者、ユーザーの存在する注文が可能なwebアプリケーションを製作中です。
カートにアイテムを入れて「情報入力へ進む」をクリックして注文情報ページに行くのですが、カートにアイテムが入っていない状態の時は注文情報ページに遷移できないようにしたいです。

*/public/cart_items/index.html.erb

<div class="container">
  <div class="row">
    <div class="col-10">
      <div class="row my-4">
        <div class="col-6">
        <h3 class="">ショッピングカート</h3>
        </div>
        <div class="col-6 text-right">
        <%= link_to "カートを空にする", public_all_destroy_path, method: :delete, class:"btn btn-danger" %>
        </div>
      </div>
      <div class="row">
        <table class="table col-12 table-bordered">
          <thead class="bg-light">
            <tr>
              <th class="text-center">商品名</th>
              <th class="text-center">単価(税込)</th>
              <th class="text-center">数量</th>
              <th class="text-center">小計</th>
              <th></th>
            </tr>
          </thead>
          <% @cart_items.each do |cart_item| %>
          <tbody>

            <td class="text-center"><%= image_tag cart_item.item.image, size: "70x50" %><%= cart_item.item.name %></td>

            <td class="text-center"><%= cart_item.item.add_tax_price.to_s(:delimited, delimiter: ',') %></td>

            <%= form_with model: cart_item, url: public_cart_item_path(cart_item.id) do |f| %>
            <td class="text-center"><%= f.select:amount,[[cart_item.amount],['1',1],['2',2],['3',3],['4',4],['5',5],['6',6],['7',7],['8',8],['9',9],['10',10]],class:"mr-1" %><%= f.submit "変更", class:"btn btn-success ml-1" %></td>
            <% end %>

            <td class="text-center"><%= (cart_item.item.add_tax_price*cart_item.amount).to_s(:delimited, delimiter: ',') %></td>

            <td class="text-center"><%= link_to "削除する", public_cart_item_path(cart_item.id),method: :delete, class:"btn btn-danger" %></td>
          </tbody>
          <% end %>
        </table>
      </div>
    </div>
  </div>
</div>
<div class="container">
  <div class="row">
    <div class="col-6 text-left">
      <%= link_to "買い物を続ける", public_root_path, class:"btn btn-primary ml-4" %>
    </div>
    <table class="table table-bordered col-2 text-right ml-5">
      <tr>
        <th class="bg-light text-center">合計金額</th>
        <td class="text-center"><%= @total_price.to_s(:delimited, delimiter: ',') %></td>
      </tr>
    </table>
  </div>
</div>
<div class="container mt-4">
  <div class="row justify-content-center">
    <div class="col-10 ">
      <div class="text-center">
       <%= link_to "情報入力に進む", new_public_order_path, class:"btn btn-success ml-4" %>
      </div>
    </div>
  </div>
</div>

*/public/cart_items_controller.rb

class Public::CartItemsController < ApplicationController
  def index
    @cart_items=current_customer.cart_items.all
    @total_price=0
    @cart_items.each do |cart_item|
      @total_price += cart_item.item.add_tax_price*cart_item.amount
    end
  end

  def create
    cart_item=CartItem.new(cart_item_params)
    cart_item.customer_id=current_customer.id
    cart_item.save
    redirect_to public_cart_items_path(cart_item.id)
  end

  def update
    cart_item=CartItem.find(params[:id])
    cart_item.update(cart_item_params)
    redirect_to  public_cart_items_path(cart_item.id)
  end

  def destroy
    cart_item=CartItem.find(params[:id])
    cart_item.destroy
    redirect_to public_cart_items_path
  end

  def all_destroy
    cart_items=current_customer.cart_items
    cart_items.destroy_all
    redirect_to public_cart_items_path
  end

 private

  def cart_item_params
    params.require(:cart_item).permit(:item_id, :amount)
  end
end

自分で試したこと

if文を使い、
もしカートアイテムが入っていれば情報入力ページへ遷移
そうでなければ遷移せずに元のページのまま
というイメージでいます。

以下の様な記述をすると考えているのですがビュー画面のcart_items/index.html.erbでlink_toとどの様に組み合わせて記述をすればよいかわかりません。コントローラのcreateアクションではフラッシュメッセージの記述の際にif文を書いたことがあります。

<% if @cart_items == nil %>
<% render public_cart_items_path %>#今現在のページ
<% else %>
<% redirect_to  new_public_order_path %>#情報入力ページ
<% end %>

解決につながるヒントを教えていただけると幸いです。
よろしくおねがしいます。

0 likes

2Answer

renderやredirect_toはActionControllerに入っているので、erbファイルでは記載が出来ないと思います。

画面遷移を行わずにカートの中身を知りたい場合はJavaScriptで確認するしかないです。

JavaScriptでの記述が大変な場合はコントローラー側で処理を記述してrenderするのが良いと思います。
ヒントと記載されているので、こんな感じですかね?

0Like

Comments

  1. @seiyarick

    Questioner

    解答ありがとうございます。
    JavaScriptは現在学習していないので今の知識(HTML,CSS,Ruby on Rails)の技術の内容で記述したいと考えています。

    コントローラ側での記述というのは私のイメージしている流れですと
    1、 ビュー内でlink_toやformの記述を書きpostメソッドやpatchメソッドでコントローラのcreateやupdateに飛ばす。
    2、コントローラに遷移後、if文の記述書き当てはまった条件によりredirect_toやrenderで遷移したいビューのpathを記述。    

    となります。
    その場合でしたら1の手順でコントローラに飛ばす際にコントローラ内にアクションを追加する必要があると考えます。この考え方は正しいのでしょうか?
    もし考え方が間違っているようでしたら解答となる答えを教えて頂きたいです。
    ヒントをお願いしておきながら申し訳ありません。
    よろしくお願いします。




                  
                             




new_public_order_pathに対応するアクションが
呼び出された時にコントローラー側で

<% if @cart_items == nil %>
<% render public_cart_items_path %>#今現在のページ
<% else %>
<% redirect_to  new_public_order_path %>#情報入力ページ
<% end %>

のような分岐をするように
処理を記述すればよろしいのでしょうか。

0Like

Comments

  1. @seiyarick

    Questioner

    解答ありがとうございます。
    そうです。コントローラ側での記述になるんですね。

    new_public_order_path#情報入力ページのコントローラはこのようになっています。

    def new
    @order=Order.new
      end

    この中の一番上に記述をするみたいなことでしょうか?
  2. ヒントと言いながらほぼ答えになってしまいますが…

    いわゆる、バリデーション(入力チェック)の話で
    先の回答者が示唆されている通りjsでのフロントエンドによるチェック、
    処理をするRails側に渡ってきてからのバックエンドによるチェックがあります。
    (大雑把に申し上げていますが)

    js抜きということなので、今回の場合はバックエンドのチェックになりますよね。

    では、newアクションの中で@cart_itemsの中身が
    nilかどうかチェックして表示先を分類すれば
    良いのではないでしょうか。
    (current_customer.cart_items.allを呼び出してその中身をチェックしても良いですが)

    恐れながら申し上げると
    Railsのレンダリングの仕組みについて
    正確に把握できていないため混乱されている節があるかと思われます。

    もしよろしければ
    以下のリンクで示したRailsガイドも同時にご参照ください。

    https://railsguides.jp/layouts_and_rendering.html
  3. @seiyarick

    Questioner

    色々教えて頂きありがとうございます。

    質問内容なんですが以下の記述で解決しました。

    カートアイテムの中に商品が入っている場合はボタンを表示するという考えにシフトしてこのような記述になりました。
    ```ruby
    <% if @cart_items.any? %>
    <%= link_to "情報入力に進む", new_public_order_path, class:"btn btn-success ml-4" %>
    <% end %>
    ```

    色々教えて頂きありがとうございました。
    @syutorum001さんのいう通りRailsのレンダリングやデータの流れがしっかり理解できていないのも詰まってしまった原因の一つだと思います。
    貼っていただいたリンクもよく確認してさらに理解を深めていこうと思います。
    ありがとうございました。勝手ながらフォローさせて頂きました。

    またよろしくお願いします。

Your answer might help someone💌