on Rails : sessionでハマる

相変わらず,カートの所でハマっています.結局update_cartはRide on Railsに載ってるそれでよろしかったのですが(勘違いは恐ろしいよ,前が見えなくなるもの),なんか今度はremove_from_cartがちゃんと動いてくれない症状に陥ってます/:(
以下心の叫び.


まずはソースコードから.

  def add_to_cart
    @item = Item.find(params[:id])
    count = params[:count].to_i
    if count > 0
      cart = session[:cart]
      assoc = cart.assoc(@item)
      if assoc then
        assoc[1] += count
      else
        cart.push [@item, count]
      end
      flash[:notice] = "#{count}個カートに入りました"
    end
    redirect_to :action => 'show', :id => @item
  end
  
  def remove_from_cart
    @cart = session[:cart]
    assoc = @cart.assoc(params[:id])
    @cart.delete(assoc)
    # session[:cart].delete(assoc)
    redirect_to :action => 'cart'
  end

Ride on Railsに載っているのを,一行改変.コメントアウトしてる部分は,ボクが勝手に付け加えた分です.なんちゅうか疑問をつらつらと上げると,

  1. @cart = session[:cart]としたら,もうそれは同じメモリを参照しているので,@cartを更新すれば勝手にsession[:cart]も更新されちゃうの?
  2. 実際に@cartの内容を見てみると,"#1"(1は個数)とかなってるんだけど,これで良いの?
  3. つーことで,なんでremove_from_cartが動かないんだYO!!!flash[:notice]で確認すると動いてるみたいだけど,結果が反映されていなければそれは動いてるとは言えない気が.


セッション管理って,思いのほか難しいなぁと思った夏休み.


で,じ〜〜〜っとコードを読んで解決!add_to_cartで,cartには[Itemオブジェクト, その個数]となっているのに,remove_from_cartでは,消すときに[Itemオブジェクトのid,その個数]としていたので,そりゃ消えないわな.結果,解決した点を上のリスト順に.

  1. 更新されちゃうみたい
  2. オブジェクトそのまんまだもの
  3. 弄ったら動いたぜ


ソースコードはこうしました.

class GoodsController < ApplicationController
...
  def add_to_cart
    @item = Item.find(params[:id])
    count = params[:count].to_i
    if count > 0
      cart = session[:cart]
      assoc = cart.assoc(@item)
      if assoc then
        assoc[1] = count # もとは+=だけど,元ある数に追加していくのは好きじゃない
      else
        cart.push [@item, count]
      end
      flash[:notice] = "現在,この本は#{count}個カートに入っています"
    end
    redirect_to :action => 'show', :id => @item
  end
  
  def remove_from_cart
    @cart = session[:cart]
    delete_from_cart(params[:id]) # なんかこう,DRYな感じにしたかった
    redirect_to :action => 'cart'
  end
  
  def update_cart
    update = false # カートの内容が更新されたら知らせる
    @cart = session[:cart]
    @cart.each do |assoc|
      item = assoc[0]
      count = params[item.id.to_s].to_i
      if count > 0
        if assoc[1] != count
          assoc[1] = count
          update = true
        end
      elsif count == 0
        delete_from_cart(item.id)
      end
    end
    if update
      flash[:notice] = 'カートの内容が更新されました'
    end
    redirect_to :action => 'cart'
  end
  
  private
  
  def delete_from_cart(id)
    assoc = @cart.assoc(Item.find(id))
    @cart.delete(assoc)
  end
...
end

add_to_cartをいじくった都合上,showアクションとビューも弄る.

  def show
    @item = Item.find(params[:id])
    assoc = session[:cart].assoc(@item)
    @count = assoc ? assoc[1] : 1
  end

show.rhtml

<%= form_tag :action => 'add_to_cart' %>
  <%= hidden_field_tag 'id', @item.id %>
  <%= @item.name %><br />
  <%= @item.price %>円 (税込)<br />
  <%= text_field_tag 'count', @count, :size => 3, :maxlength => 3 %>個<br />
  <%= submit_tag 'カートに入れる' %>
<%= end_form_tag %>
<%= link_to 'お支払いに進む', :action => 'cart' %>
<%= link_to 'お買い物を続ける', :action => 'list' %>

これぞ自己満足:p・・・進まNEEE!!!orz