質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.77%

Ruby 特定のsessionだけ削除

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,261

shirou

score 15

 前提・実現したいこと

@cart配列より取り出した各要素に削除ボタンを追加した際に、該当する各要素をボタンを押して削除出来るようにしたい。

 発生している問題・エラーメッセージ

@cart.updateの場合

NoMethodError in CartController#update
undefined method `update' for #<Array:0x00007f8d82d455f0>


@cart.delete([:id])の場合
変化なし。
terminalでは以下のような形になります。
delete/delete_atメソッドを用いても、railsの方でエラーは起きないのですが、削除した内容も反映されないといった具合になります。

Started PATCH "/cart/1" for 127.0.0.1 at 2018-08-25 16:19:19 +0900
Processing by CartController#update as HTML
  Parameters: {"authenticity_token"=>"uCSoRxnlGlRIT/Z4YHFcppIA91GQpnIqbLXMtTZnOnsFi+1X4TNMGN49eBZO+qzgd+kCcZovUw48uosD2pdLjQ==", "id"=>"1"}
  Item Load (0.4ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/cart_controller.rb:26
  CACHE Item Load (0.0ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/cart_controller.rb:26
  Item Load (0.4ms)  SELECT  "items".* FROM "items" WHERE "items"."id" = $1 LIMIT $2  [["id", 3], ["LIMIT", 1]]
  ↳ app/controllers/cart_controller.rb:26
Redirected to http://localhost:3000/cart
Completed 302 Found in 5ms (ActiveRecord: 0.8ms)

 該当のソースコード

cart.controller.rb

class CartController < ApplicationController
  # before_action :set_cart, only: [:update]
  def index
    if session[:cart] != nil
      session[:cart].sort!
      @cart = session[:cart].map { |item_id| Item.find(item_id) }
    end
  end

  def create
    session[:cart] = [] unless session[:cart]
    session[:cart] << params[:item_id]
    redirect_to top_path, notice: 'カートに商品を入れました'
  end

  def update
    # 配列の中から特定の要素を削除
    # session.delete([:item_id])
    # @cart.update
    # session[:cart].delete([:id])
    # @cart.delete([:id])
    @cart = session[:cart].map { |item_id| Item.find(item_id) }
    @cart.delete
    redirect_to cart_index_path
    # session[:cart]
    # =>["1", "1", "3", "3"]
    #@cart
    # => [#<Item id: 1, name: "1", description: "1", price: 1, created_at: "2018-08-23 09:53:01", updated_at: "2018-08-23 09:53:01", image: "masamune.jpg">, #<Item id: 1, name: "1", description: "1", price: 1, created_at: "2018-08-23 09:53:01", updated_at: "2018-08-23 09:53:01", image: "masamune.jpg">, #<Item id: 3, name: "2", description: "2", price: 2, created_at: "2018-08-23 09:54:19", updated_at: "2018-08-23 09:54:19", image: "transcendence.jpg">, #<Item id: 3, name: "2", description: "2", price: 2, created_at: "2018-08-23 09:54:19", updated_at: "2018-08-23 09:54:19", image: "transcendence.jpg">]
  end

  def destroy

    reset_session
    # @cart = session[:cart].map { |item_id| Item.find(item_id) }
    # @cart.destroy
    # @cart =Item.find(@item_id)
    # @cart.destroy
    redirect_to cart_index_path
  end

  # private
  #   # Use callbacks to share common setup or constraints between actions.
  #   def set_cart
  #     @cart = session[:cart].map { |item_id| Item.find(item_id) }
  #   end
  #
  #   # Never trust parameters from the scary internet, only allow the white list through.
  #   def cart_params
  #     params.require(:cart)
  #   end
end

index.html.rb

<tbody>
<h1>注文一覧</h1>
<% sum = 0 %>
<% if @cart.blank? %>
<%= "カートは空です" %><br>
<% else %>
<% @cart.each do |item| %>
<tr>
<td>商品番号: <%= item.id %></td>
<td>価格: <%= item.price %></td><br>
<% sum += item.price %>
<%= button_to "Clear Product", cart_path(item), method: :patch, data: { confirm: 'Are you sure?' } %><br>
<% end %><br>
<!-- 合計金額: <%= sum %>円<br> -->

</tr>
</tbody>
<br>
<% end %>

 試したこと

ソースコードでコメントアウトしている内容になります。

    # session.delete([:item_id])
    # @cart.update
    # session[:cart].delete([:id])
    # @cart.delete([:id])

 補足情報(FW/ツールのバージョンなど)

Rails 5.2

 追記

index.html.erbにて

<% if @cart.blank? %>
<%= "カートは空です" %><br>
<% else %>
<% @cart.each do |item| %>
<tr>
<td>商品番号: <%= item.id %></td>
<td>価格: <%= item.price %></td><br>
<% sum += item.price %>
<%= button_to "Clear Product", cart_path(item), method: :patch, data: { confirm: 'Are you sure?' } %><br>
<% end %><br>


cart_path(item)とすることで送られているデータはcart.controller def indexにて定義された @cart = session[:cart].map { |item_id| Item.find(item_id) }の @cartではなく、 def updateにて定義した @cartが入ること。
そしてCartはモデルではない為に、destroy,updateなどのメソッドは継承されていない為使用不可なこと。
しかし @cart = Item.find(params[:id])と記述を変えることで、 @cart.destroyを実行するとItemモデルのdestroyを実行することで再び大元のデータを消してしまうこと。
その代わり、 @cartは削除したいデータそのものを引っ張ってきていること。。
ここまでが分かりました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

コードを見るに、@cartはsessionのエントリーの一つをmapで取得したものなので、そのものではなく複製されたものです。
deleteした後、再度sessionに書き込む必要があるんじゃないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/26 14:15 編集

    回答ありがとうございます!
    @cartは複製されたものであってそのものではないという回答を頂きまして
    記述を変更した所、`@cart.id`で指定している為カート内の同じ商品は全て削除されてしまう状況ではありますがひとまず仮実装が出来ました。

    ```ruby
    @cart = Item.find(params[:id])
    session[:cart].reject!{|n| n.to_i == @cart.id}
    ```

    もし宜しければ再度質問があるのですが、追記に記しました`cart_path(item)`より受け取った値が`@cart`配列要素の何番目に該当するのか`controller.rb`にて調べる、特定する方法はありますでしょうか?

    キャンセル

  • 2018/08/27 14:36

    質問の表題は満たされたため、解答済みにしたのですよね。
    手間であっても、別途質問をされたほうが良いと思います。そのほうが他の方も回答しやすいかと。

    キャンセル

  • 2018/08/31 15:51

    おっしゃられる通りです。
    その後なんとか解決出来ましたので、この場は解決済みのままにしておきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る