ITコンサルの日常

ITコンサル会社に勤務する普通のITエンジニアの日常です。

「RailsによるアジャイルWebアプリケーション開発」9章まで読了

部分テンプレートのファイル名は、_cart_item.rhtmlじゃなくて、_cart_item.html.erbです。この手の読み替えは延々と続くなあ。
ところで、AJAXの実装を入れたのに動かない!って思ってたら、よく見たらサイドバーの数量がインクリメントされてて動いてました。
「顧客を満足させるには」のコラムに書いてある、

「あら、気づかなかったわ」

っていう状態そのまま(汗


ところで、Yellow Fade Techniqueを入れた辺りから、

RJS error:

TypeError: $("current_item") has no properties

とかいうエラーがポップアップ表示されるように。
色々調べてみたら、app/models/cart.rbの修正がマズってたらしい。
elseも変わってるのに気づかなかったよ。。本どおり修正したら無事エラーでなくなりました。


というわけで、自由課題。

現行のカートは、ページ全体を再描画することで、ユーザがカートを空にしたとき非表示にしています。この動作ではなく、Script.aculo.us blind_upを使えるようにアプリケーションを変更することはできますか。

まず、「カートを空にする」ボタンをAJAX対応にする
_cart.html.erb

<% form_remote_tag :url => {:action => :empty_cart } do %>
  <%= submit_tag "カートを空にする on AJAX", :disabled => !@order.nil? %>
<% end %>

続いて、RJSテンプレートを作成する。
empty_cart.rjs

page[:cart].visual_effect :blind_up

これで出来上がり。だが、JavaScript無効対策を入れておく。

store_controller.rb

  def empty_cart
    session[:cart] = nil
    redirect_to_index unless request.xhr?
  end

ブラウザのJavaScriptが無効にされている場合でも、自分で行った変更内容が機能しますか。

試しにJavaScriptをoffにしてみた。問題なく動いた。

カート内の新しい項目に、別の視覚効果をつけてみましょう。例えば、初期状態を非表示に設定して拡大するように表示させることはできますか。

add_cart.rjsをこんな風に変えてみる。

#page[:current_item].visual_effect :highlight,
#				  :startcolor => "#88ff88",
#				  :endcolor => "114411"

page[:current_item].visual_effect :grow

なんかイマイチっぽいけど、まあ一応動いてる。
http://script.aculo.us/docs/Effect.Grow.html
を参考にしました。

AJAXコードと最初のページ表示でカート項目の部分テンプレートを共有しても問題が発生しませんか。

うーん、ちょっと言っている意味が分からず。。
特に動作は問題なさそうですが。

カート内の各項目の隣にリンクを追加しましょう。これをクリックすると商品の数量を減らすアクションが呼び出され、数量が0になるとカートからその項目が削除されるように設定してみましょう。

まずは、減らすボタンの追加。
app/views/store/_cart.html.erb

  <td><%= button_to "減らす", :action => :remove_from_cart, :id => cart_item.product %></td>

でもって、remove_from_cartアクションの追加
app/controllers/store_controller.rb

  def remove_from_cart
    begin
      product = Product.find(params[:id])
    rescue
      logger.error("無効な商品#{params[:id]}にアクセスしようとしました")
      redirect_to_index("無効な商品です")
    else
      @cart = find_cart
      @cart.remove_product(product)
      redirect_to_index unless request.xhr?
    end
  end

add_to_cartメソッドのコピーです。コードが重複してて見苦しい。。

続いて、セッションから実際にproductを1個減らすためのコードを追加。

app/models/cart.rb

  def remove_product(product)
    current_item = @items.find{|item| item.product == product}
    if current_item
      current_item.decrement_quantity
      if current_item.quantity == 0 then
        @items.delete(current_item)
      end
    end
  end

でもってデクリメントの実装
app/models/cart_item.rb

  def decrement_quantity
    @quantity -= 1
  end

とりあえず動いてるっぽい。

次にAJAXを追加してみましょう。

疲れたので明日にしよう。。

(2008/5/8追記)
app/views/_cart_item.html.erbの減らすボタンところを、こんな感じにする。

    <% form_remote_tag :url => {:action => :remove_from_cart, :id => cart_item.product } do %>
      <%= submit_tag "減らす" %>
    <% end %>

でもって、rjsを作る。
app/views/remove_from_cart.rjs

page.replace_html("cart", :partial => "cart", :object => @cart)

JavaScript無効対策は、昨日のうちに書いてしまったのでこれだけ。
案外あっさりと出来ましたとさ。