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用户管理模块

转载请注明: 转自船长日志, 本文链接地址: http://www.cslog.cn/Content/ruby_on_rails_eshop_checkout/

此条目发表在 Ruby on Rails 分类目录。将固定链接加入收藏夹。

发表评论