Ruby on Rails實戰–創建一個網上商店B前台

上一節: Ruby on Rails實戰–創建一個網上商店a
本節創建商店的前台模塊, 也就是客戶看到的頁面.

1.創建前台Controller Store:depot> ruby script/generate controller store index
最後的index創建一個index Action,用作默認action

2.創建一個session,用來保存購物籃數據
depot> rake db:sessions:create
然後
depot> rake db:migrate
(users of Rails applications must have cookies enabled in their browsers.???)
在config/environment.rb中將
config.action_controller.session_store = :active_record_store
語句前的註解符#去除,啟動數據庫保存session功能
*使用depot> rake db:sessions:clear可以清空當前session內容

3.創建前台的Store的Controller
修改depot/app/controllers/store_controller.rb文件為
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class StoreController < ApplicationController
  def index
    @products = Product.find_products_for_sale
  end
  #find_products_for_sale將在model裡面定義,見下文
  #下面是購物籃添加程序
  def add_to_cart
    begin
      @product = Product.find(params[:id])
    rescue
      logger.error("Attempt to access invalid product #{params[:id]}")
      redirect_to_index("Invalid product")
    else
      @cart = find_cart
      @cart.add_product(@product)
    end
  end
  #上面的begin…rescue…else…end用來處理錯誤
  #當begin出錯,即找不到當前ID的商品時進行rescue處理,以防止入侵或意外出錯
  #上面的logger.eeror用來記錄錯誤log,對應log目錄里的development.log文件
  # @product = Product.find(params[:id])可以接 add_to_cart/1 樣式傳來的request.
  #上面的redirect_to_index見下面代碼
  #上面的find_cart見下面代碼
  #add_product()代碼見下面.

  #下面是購物籃清空程序
  def  empty_cart
    session[:cart] = nil
    redirect_to_index("Your cart is currently empty")
  end

  private #開始定義局部代碼

#一個高壓縮處理了的錯誤信息顯示代碼
  def redirect_to_index(msg)
    flash[:notice] = msg #用來顯示出錯信息
    redirect_to :action => :index
  end
#flash[:notice] = msg #用來顯示flash信息
#redirect_to :action => :index 可用來轉移頁面.

#使用session來保存購物籃數據
  def find_cart
    session[:cart] ||= Cart.new
  end
end
#上面的||=語句用來創建檢查session,如果存在則調出數據,如果不存在生成新session
#!!!好符號化的語言啊!!!日本人不太懂英語吧.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

4.創建model:
修改depot/app/models/product.rb文件為:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class Product < ActiveRecord::Base
  def self.find_products_for_sale
    find(:all, :order => "title")
  end
 #用 self.前綴,定義class method
  #上面的find(:all, :order => "title")讓程序列出所有商品,按標題排序
  #以下為原來的效驗代碼….
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

手動創建一個depot/app/models/cart.rb, 作為購物籃的model,內容如下:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class Cart
  include Reloadable #手動創建的model要加入這句,以後服務器才會自動刷新
  #Whenever youcreatea non-database model, youneed toinclude a includeReloadable directive in the source.
  attr_reader :items 
  def initialize #初始化method
    @items = [] # @items = []來賦空集.
  end
  def add_product(product)
    existing_product = @items.find {|item| item.product == product}
    if existing_product #如果籃中已有商品,累加數量
      existing_product.increment_quantity
    else
      @items << CartItem.new(product)
    end
  end
  def total_price
    @items.inject(0) { |sum, item| sum + item.price }
  end
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

手動創建一個depot/app/models/cart_item.rb model,用來處理購物籃內的商品,內容如下:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
class CartItem
  include Reloadable #見上文
  attr_reader :product, :quantity
  def initialize(product)
    @product = product
    @quantity = 1
  end
  def increment_quantity
    @quantity += 1
  end
  def title
    @product.title
  end
  def price
    @product.price * @quantity
  end
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

5.創建View:
修改depot/app/views/store/index.rhtml文件為:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<% for product in @products -%>
 <div class="entry">
  <img src="<%= product.image_url %>"/>
  <h3><%= h(product.title) %></h3>
  <%= product.description %>
  <span class="price"><%= format_price(product.price) %></span>
  <%= button_to "Add to Cart", :action => :add_to_cart, :id => product %>
 </div>
 <br />
<% end %>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*上面的product.description為使描述帶有HTML代碼,沒有使用h(),帶有安全隱患.
*上面的format_price為一個helper,來用格式化整數形的價格.見下文.
*上面的button_to將生成一個按鈕,鏈接到add_to_cart action,用於向購物籃添加商品,它將以post方向向add_to_cart action傳送商品ID信息. (post比get好???)
(And a POST request is just the ticket when we want to do something like add an item to a cart.)
*button_to的作用實際上相應於生成如下代碼:
<form method="post" action="/store/add_to_cart/1" class="button-to">
<input type="submit" value="Add to Cart" />
</form>

手動建立一個添加商品頁面的view depot/app/views/store/add_to_cart.rhtml,文件內容如下:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<div class="cart-title">Your Cart</div>
<table>
 <% for cart_item in @cart.items %>
  <tr>
   <td><%= cart_item.quantity %> &times;</td>
   <td><%= h(cart_item.title) %></td>
   <td class="item-price"><%= format_price(cart_item.price) %></td>
  </tr>
 <% end %>
 <tr class="total-line">
  <td colspan="2">Total</td>
  <td class="total-cell"><%= format_price(@cart.total_price) %></td>
 </tr>
</table>
<%= button_to "Empty cart", :action => :empty_cart %>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
* &times;生成一個乘號.

6.增加format_price helper
修改depot/app/helpers/store_helper.rb文件為:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
module StoreHelper
  def format_price(amount)
    dollars, cents = amount.divmod(100)
    sprintf("$%d.%02d", dollars, cents)
  end
end
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*上面的divmod是一個內置方法. 用它將以分為單位的整數形價格分為元和分兩部分.

7.給view添加一個模板
修改:depot/app/views/layouts/store.rhtml文件內容為:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
<html>
 <head>
  <title>Pragprog Books Online Store</title>
  <%= stylesheet_link_tag "depot", :media => "all" %>
 </head>
 <body id="store">
  <div id="banner">
   <img src="/images/logo.png"/>
   <%= @page_title || "Pragmatic Bookshelf" %>
  </div>
  <div id="columns">
   <div id="side">
    <a href="http://www….">Home</a><br />
    <a href="http://www…./faq">Questions</a><br />
    <a href="http://www…./news">News</a><br />
    <a href="http://www…./contact">Contact</a><br />
   </div>
   <div id="main">
    <!–下面的代碼顯示錯誤提示信息–>
    <% if flash[:notice] -%>
     <div id="notice"><%= flash[:notice] %></div>
    <% end -%>
    <!–下面的代碼顯示不同action的子view內容–>
    <%= @content_for_layout %>
    <!–其它的內容為共用模板–>
   </div>
  </div>
 </body>
</html>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
*這個和controller同名的layout文件為view的默認模板.
*<%= @page_title || "Pragmatic Bookshelf" %> ???

到這裡用戶界面已經基本完成.
調試使用 http://localhost:3000/store/訪問

下一節:Ruby on Rails實戰–創建一個網上商店C小試Ajax

此條目發表在 Ruby on Rails 分類目錄。將固定鏈接加入收藏夾。

Ruby on Rails實戰–創建一個網上商店B前台》有 1 條評論

  1. CDMYNAME 說:

    smart man !
    thank you very much !
    It’s suitable for beginners.

發表評論