我正在通過使用Rails 4進行敏捷Web開發4,停留在第11章迭代F4上。該部分的目標是僅在購物車中有物品時才顯示購物車div,否則通過display: none
將其隱藏。當點擊空購物車按鈕時,購物車可以正確隱藏自身,但當物品添加到購物車時,購物車將不會顯示,除非手動刷新頁面。AJAX在手動頁面刷新之前沒有渲染更新
這裏的服務器輸出的外觀,當一個項目被添加到一個空的購物車,如:
Started POST "/line_items?product_id=2" for ::1 at 2015-05-10 18:51:44 -0700
Processing by LineItemsController#create as JS
Parameters: {"authenticity_token"=>"v2zcRr2CPsfZP3/qI8l5m0HWdDoOiiyl5oiZxvpYKXp7K2ecXizzCZA37DLm7PwYuSAgemogwjjnDHz4NbavGA==", "product_id"=>"2"}
Cart Load (0.2ms) SELECT "carts".* FROM "carts" WHERE "carts"."id" = ? LIMIT 1 [["id", 21]]
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 2]]
LineItem Load (0.1ms) SELECT "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ? AND "line_items"."product_id" = ? LIMIT 1 [["cart_id", 21], ["product_id", 2]]
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "line_items" ("product_id", "cart_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["product_id", 2], ["cart_id", 21], ["created_at", "2015-05-11 01:51:44.341300"], ["updated_at", "2015-05-11 01:51:44.341300"]]
(1.1ms) commit transaction
LineItem Load (0.2ms) SELECT "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ? [["cart_id", 21]]
Product Load (0.2ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 2]]
Rendered line_items/_line_item.html.erb (2.0ms)
Rendered carts/_cart.html.erb (6.7ms)
Rendered line_items/create.js.erb (8.9ms)
而這裏的輸出是什麼樣子,當我刷新:
Started GET "/" for ::1 at 2015-05-10 18:57:17 -0700
Processing by StoreController#index as HTML
Cart Load (0.1ms) SELECT "carts".* FROM "carts" WHERE "carts"."id" = ? LIMIT 1 [["id", 21]]
Product Load (2.2ms) SELECT "products".* FROM "products" ORDER BY "products"."updated_at" DESC LIMIT 1
Product Load (0.2ms) SELECT "products".* FROM "products" ORDER BY "products"."title" ASC
Rendered store/index.html.erb within layouts/application (17.9ms)
LineItem Exists (0.2ms) SELECT 1 AS one FROM "line_items" WHERE "line_items"."cart_id" = ? LIMIT 1 [["cart_id", 21]]
LineItem Load (0.2ms) SELECT "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ? [["cart_id", 21]]
Product Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", 2]]
Rendered line_items/_line_item.html.erb (1.6ms)
Rendered carts/_cart.html.erb (6.2ms)
Completed 200 OK in 129ms (Views: 124.7ms | ActiveRecord: 3.0ms)
這裏是我的LineItemsController,包含create
當我將該物品添加到空購物車時觸發的操作:
class LineItemsController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:create]
before_action :set_line_item, only: [:show, :edit, :update, :destroy]
# GET /line_items
# GET /line_items.json
def index
@line_items = LineItem.all
end
# GET /line_items/1
# GET /line_items/1.json
def show
end
# GET /line_items/new
def new
@line_item = LineItem.new
end
# GET /line_items/1/edit
def edit
end
# POST /line_items
# POST /line_items.json
def create
product = Product.find(params[:product_id])
@line_item = @cart.add_product(product.id)
respond_to do |format|
if @line_item.save
format.html { redirect_to store_url }
format.js { @current_item = @line_item }
format.json { render action: 'show', status: :created, location: @line_item }
else
format.html { render action: 'new' }
format.json { render json: @line_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /line_items/1
# PATCH/PUT /line_items/1.json
def update
respond_to do |format|
if @line_item.update(line_item_params)
format.html { redirect_to @line_item, notice: 'Line item was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: @line_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /line_items/1
# DELETE /line_items/1.json
def destroy
@line_item.destroy
respond_to do |format|
format.html { redirect_to line_items_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_line_item
@line_item = LineItem.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def line_item_params
params.require(:line_item).permit(:product_id)
end
end
這是我StoreController,包含index
行動由手動刷新觸發:
class StoreController < ApplicationController
include CurrentCart
before_action :set_cart
def index
@products = Product.order(:title)
end
end
看來,當我清空購物車和檢查DIV中,display: none
屬性應用(因爲它應該是)從application.html.erb:
<!DOCTYPE html>
<html>
<head>
<title>Pragprog Books Online Store</title>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
</head>
<body class='<%= controller.controller_name %>'>
<div id="banner">
<%= image_tag("logo.png") %>
<%= @page_title || "Pragmatic Bookshelf" %>
</div>
<div id="columns">
<div id="side">
<%= hidden_div_if(@cart.line_items.empty?, id: 'cart') do %>
<%= render @cart %>
<% end %>
<ul>
<li><a href="http://www....">Home</a></li>
<li><a href="http://www..../faq">Questions</a></li>
<li><a href="http://www..../news">News</a></li>
<li><a href="http://www..../Contact">Contact</a></li>
</ul>
</div>
<div id="main">
<%= yield %>
</div>
</div>
</body>
</html>
的hidden_div_if
方法是在ApplicationHelper.rb:
module ApplicationHelper
def hidden_div_if(condition, attributes = {}, &block)
if condition
attributes["style"] = "display: none"
end
content_tag("div", attributes, &block)
end
end
但是,當我在添加項目後檢查購物車div時,仍然應用display: none
。我錯過了什麼?
如果它的事項,這是我CartsController:
class CartsController < ApplicationController
before_action :set_cart, only: [:show, :edit, :update, :destroy]
rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart
# GET /carts
# GET /carts.json
def index
@carts = Cart.all
end
# GET /carts/1
# GET /carts/1.json
def show
end
# GET /carts/new
def new
@cart = Cart.new
end
# GET /carts/1/edit
def edit
end
# POST /carts
# POST /carts.json
def create
@cart = Cart.new(cart_params)
respond_to do |format|
if @cart.save
format.html { redirect_to @cart, notice: 'Cart was successfully created.' }
format.json { render :show, status: :created, location: @cart }
else
format.html { render :new }
format.json { render json: @cart.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /carts/1
# PATCH/PUT /carts/1.json
def update
respond_to do |format|
if @cart.update(cart_params)
format.html { redirect_to @cart, notice: 'Cart was successfully updated.' }
format.json { render :show, status: :ok, location: @cart }
else
format.html { render :edit }
format.json { render json: @cart.errors, status: :unprocessable_entity }
end
end
end
# DELETE /carts/1
# DELETE /carts/1.json
def destroy
@cart.destroy if @cart.id == session[:cart_id]
session[:cart_id] = nil
respond_to do |format|
format.html { redirect_to store_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cart
@cart = Cart.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def cart_params
params[:cart]
end
def invalid_cart
logger.error "Attempt to access invalid cart #{params[:id]}"
redirect_to store_url, notice: 'Invalid cart'
end
end