「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無効対策は、昨日のうちに書いてしまったのでこれだけ。
案外あっさりと出来ましたとさ。