Ruby on Rails實戰–創建一個網上商店D收銀台

上一節:Ruby on Rails實戰–創建一個網上商店C小試Ajax
本節完成收銀台功能. 為頁面新增一個結賬按鈕,用戶挑選商品後點擊結賬按鈕時出現一個用戶資料表單,用戶填交後,系統將商品信息和用戶信息保存到數據庫中.

創建order model
depot> ruby script/generate model order
修改depot/db/migrate/005_create_orders.rb 內容為:
class CreateOrders < ActiveRecord::Migration
  def self.up
    create_table :orders do |t|
      t.column :name, :string
      t.column :address, :text
      t.column :email, :string
      t.column :pay_type, :string, :limit => 10
    end
  end

  def self.down
    drop_table :orders
  end
end

創建line_item model,
depot>ruby script/generate model line_item
修改depot/db/migrate/006_create_line_items.rb文件內容為:
class CreateLineItems < ActiveRecord::Migration
  def self.up
    create_table :line_items do |t|
      t.column :product_id, :integer, :null => false
      t.column :order_id, :integer, :null => false
      t.column :quantity, :integer, :null => false
      t.column :total_price, :integer, :null => false
    end
 #創建兩個foreign key
    execute "alter table line_items
            add constraint fk_line_item_products
            foreign key (product_id) references products(id)"

    execute "alter table line_items
            add constraint fk_line_item_orders
            foreign key (order_id) references orders(id)"
  end
 
  def self.down
    drop_table :line_items
  end
end

向數據庫應用
depot> rake db:migrate

關聯model:
在depot/app/models/order.rb和
depot/app/models/product.rb兩文件者加入:
has_many :line_items
聲明這兩個model下有多個line_items
在depot/app/models/line_item.rb文件中加入:
belongs_to :order
belongs_to :product
聲明這個model從屬於order和product
*if a table has foreign keys, the corresponding model should have a belongs_to for each.

添加結賬按鈕:
在depot/app/views/store/_cart.rhtml文件:
<%= button_to "Empty cart", :action => :empty_cart %>
行上方加入:
<%= button_to "Checkout", :action => :checkout %>

checkout action
在depot/app/controllers/store_controller.rb文件中定義checkout action 和save_order action:
  def checkout
    @cart = find_cart
    if @cart.items.empty?
 #判斷籃中是否為空
      redirect_to_index("Your cart is empty")
    else
      @order = Order.new
    end
  end

  def save_order
    @cart = find_cart
    @order = Order.new(params[:order])
    @order.add_line_items_from_cart(@cart)
    if @order.save #保存數據
      session[:cart] = nil #清空購物籃
      redirect_to_index("Thank you for your order")
    else
      render :action => :checkout
    end
  end

相應 checkout 的view文件depot/app/views/store/checkout.rhtml內容為:
<div class="depot-form">
 <%= error_messages_for ‘order’ %>
 <fieldset>
  <legend>Please Enter Your Details</legend>
  <% form_for :order, :url => { :action => :save_order } do |form| %>
   <p>
    <label for="order_name">Name:</label>
    <%= form.text_field :name, :size => 40 %>
   </p>
   <p>
    <label for="order_address">Address:</label>
    <%= form.text_area :address, :rows => 3, :cols => 40 %>
   </p>
   <p>
    <label for="order_email">E-Mail:</label>
    <%= form.text_field :email, :size => 40 %>
   </p>
   <p>
    <label for="order_pay_type">Pay with:</label>
    <%=
     form.select :pay_type,
     Order::PAYMENT_TYPES,
     #這個下拉列表內容另定義
     :prompt => "Select a payment method"
    %>
   </p>
   <%= submit_tag "Place Order", :class => "submit" %>
  <% end %>
 </fieldset>
</div>
上面藍色的代碼用來組建form.

在depot/app/models/order.rb文件中定義上面下拉列表的PAYMENT_TYPES內容:
  PAYMENT_TYPES = [
  # 顯示文字 數據庫內容
  [ "Check", "check" ],
  ["Credit card", "cc" ],
  ["Purchase order", "po" ]
  ]
  #校驗用戶名,地址,信箱地址和支付方式是否為空
  validates_presence_of :name, :address, :email, :pay_type
  #校驗支付方式是否合法(加強安全性)
  validates_inclusion_of :pay_type, :in => PAYMENT_TYPES.map {|disp, value| value}
 
  #定義上面用到的add_line_items_from_cart()
   def add_line_items_from_cart(cart)
    cart.items.each do |item|
      li = LineItem.from_cart_item(item)
      line_items << li
    end
  end

修改depot/app/models/line_item.rb文件內容為:
class LineItem < ActiveRecord::Base
  belongs_to :order
  belongs_to :product
  def self.from_cart_item(cart_item)
    li = self.new
    li.product = cart_item.product
    li.quantity = cart_item.quantity
    li.total_price = cart_item.price
    li
  end
end

在depot/app/views/store/add_to_cart.rjs文件中加入:
page.select(‘div#notice’).each { |div| div.hide }
搜索頁面中id=notice的div,如有找到,將div隱藏.
在用戶結賬後繼續購物時隱藏結賬成功提示語.

本節結束

下一節:Ruby on Rails實戰–創建一個網上商店E用戶管理模塊

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

發表評論