在前面的內容裡,我們演示了怎樣構建一個商品的列表,這次,我們在前面內容的基礎上,構建一個簡單的購物車。
1.首先我們要來創建一個保存客戶購物信息的表:
數據庫腳本:
drop table if exists line_items; create table line_items ( id int not null auto_increment, product_id int not null, quantity int not null default 0, unit_price decimal(10,2) not null, constraint fk_items_product foreign key (product_id) references products(id), primary key (id) );
之後在PhpMyAdmin中創建表,然後使用Rails命令行創建line_item表對應的類:
depot> ruby script/generate model LineItem
(創建的詳細步驟可以參考前面的幾篇隨筆)
2.給LineItem和Product創建主從關系:
打開\rails_apps\depot\app\models目錄下的line_item.rb文件,修改文件內容為:
class LineItem < ActiveRecord::Base belongs_to :product end
可以看到belongs_to :product這句給LineItem和Product創建了主從關系。
3.現在,我們可以添加ruby代碼了。
首先是rails_apps\depot\app\controllers目錄下的store_controller.rb文件,給其中添加方法:
private def find_cart session[:cart] ||= Cart.new end
實際上,在上篇隨筆中,在rails_apps\depot\app\views\store目錄下的index.rhtml文件中,我們可以看到這樣的代碼:
<%= link_to 'Add to Cart', {:action => 'add_to_cart', :id => product }, :class => 'addtocart' %>
這句代碼的就是給Add to Cart鏈接指定它的Action,相應的,我們要在store_controller.rb中添加add_to_cart方法
def add_to_cart product = Product.find(params[:id]) @cart = find_cart @cart.add_product(product) redirect_to(:action => 'display_cart') end
上面的代碼中,首先調用了Product的find方法,然後是store_controller的find_cart方法,接下來調用Cart的add_product方法,然後在重定向頁面,Action是display_cart。
好了,下面我們來編寫這些方法中要用到的代碼。
l 創建Cart類,我們在app/models目錄下,創建cart.rb文件,代碼如下:
class Cart attr_reader :items attr_reader :total_price def initialize @items = [] @total_price = 0.0 end def add_product(product) << @items << LineItem.for_product(product) @total_price += product.price end end
l 給LineItem添加一個方法for_product,代碼如下:
class LineItem < ActiveRecord::Base belongs_to :product def self.for_product(product) self.new item = self.new item.quantity = 1 item.product = product item.unit_price = product.price item end end
l 在store_controller.rb文件中添加方法display_cart,代碼:
def display_cart @cart = find_cart @items = @cart.items end
l 我們再來創建一個顯示Cart的頁面。
在rails_apps\depot\app\views\store目錄下,新建,一個display_cart.rhtml文件,修改內容:
<h1>Display Cart</h1> <p> Your cart contains <%= @items.size %> items.</p>
l 這時候,如果我們點擊Add to Cart鏈接的話,會出現一個error頁面,這是因為我們還沒有定義session。這一步我們需要修改rails_apps\depot\app\controllers目錄下的application.rb文件,使其內容為:
# Filters added to this controller apply to all controllers in the application.# Likewise, all the methods added will be available for all controllers.class ApplicationController < ActionController::Base # Pick a unique cookie name to distinguish our session data from others' #session:session_key => '_depot_session_id' model :cart model :line_item end
l 到此,再點擊點擊Add to Cart鏈接,應該會出現一個正常的頁面了。
4.現在,雖然我們已經有了一個可以運行的頁面,但是你會發現,如果你多次添加同一件商品,在display_cart頁面上會一條一條顯示。我們來完善一下這些代碼,修改add_product方法:
def add_product(product) item = @items.find {|i| i.product_id == product.id} if item item.quantity += 1 else item = LineItem.for_product(product) @items << item end @total_price += product.price end
最後再美化下display_cart頁面:
<html> <head> <%= stylesheet_link_tag "scaffold", "depot", "admin", :media => "all" %> </head> <div id="cartmenu"> <ul> <li><%= link_to 'Continue shopping', :action => "index" %></li> <li><%= link_to 'Empty cart', :action => "empty_cart" %></li> <li><%= link_to 'Checkout', :action => "checkout" %></li> </ul> </div> <table cellpadding="10" cellspacing="0"> <tr class="carttitle"> <td rowspan="2">Qty</td> <td rowspan="2">Description</td> <td colspan="2">Price</td> </tr> <tr class="carttitle"> <td>Each</td> <td>Total</td> </tr> <% for item in @items product = item.product -%> <tr> <td><%= item.quantity %></td> <td><%= h(product.title) %></td> <td align="right"><%= item.unit_price %></td> <td align="right"><%= item.unit_price * item.quantity %></td> </tr> <% end %> <tr> <td colspan="3" align="right"><strong>Total:</strong></td> <td id="totalcell"><%= @cart.total_price %></td> </tr> </table> </html>
OK,大功告成了,來看看最後的效果: