Agile Web Development with Rails第十二章笔记——任务G:付款

如标题所示,这一章的主要目的就是完成付款功能,整个任务由以下几个模块迭代完成。

迭代G1:获取订单

订单是商品项目及其购买交易的细节的集合,为了存储购买交易的细节,下面我们需要创建表orders。

使用脚手架创建订单表:
rails generate scaffold order name:string address:text email:string pay_type:string

为了将用户所选商品与订单相关联,为line_item添加属性order_id(是否可以为order添加属性line_item_id)

rails generate migration add_order_id_to_line_item order_id:integer

应用迁移

rake db:migrate

1、创建获取订单的表单

动作设计如下,点击check out按钮,页面跳转至填写订单页面。

                                                              

a、添加check out按钮

<!--app\views\carts\_cart.html.erb-->
<div class="cart_title">Your Cart</div>
<table>
  <%= render(cart.line_items) %>
  <tr class="total_line">
    <td colspan="2">Total</td>
    <td class="total_cell"><%= number_to_currency(cart.total_price) %></td>
  </tr>
</table>
<%= button_to "Checkout", new_order_path, :method => :get %>
<%= button_to 'Empty cart', cart, :method => :delete,
    :confirm => 'Are you sure?' %>

b、控制器中判断购物车是否为空(跳至首页给出提示或者跳至新建订单页面)

  # orders_controller.erb
  def new
    @cart = current_cart
    if @cart.line_items.empty?
      redirect_to store_url, :notice => "Your cart is empty"
      return
    end

    @order = Order.new
    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @order }
    end
  end

完成这一步之后点击测试,新建订单页面如图:

页面标签对应的输入框不够美观,下面通过帮助方法更改输入框的外观类型。

新建订单界面:

<!--app\views\orders\new.html.erb-->
<div class="depot_form">
  <fieldset>
    <legend>Please Enter Your Details</legend>
    <%= render 'form' %>
  </fieldset>
</div>
这个模版利用了一个同文件夹下名叫_form的局部模版
<%= form_for(@order) do |f| %>
  <% if @order.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@order.errors.count, "error") %>
      prohibited this order from being saved:</h2>

      <ul>
      <% @order.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, :size => 40 %>
  </div>
  <div class="field">
    <%= f.label :address %><br />
    <%= f.text_area :address, :rows => 3, :cols => 40 %>
  </div>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, :size => 40 %>
  </div>
  <div class="field">
    <%= f.label :pay_type %><br />
    <%= f.select :pay_type, Order::PAYMENT_TYPES,
                  :prompt => 'Select a payment method' %>
  </div>
  <div class="actions">
    <%= f.submit 'Place Order' %>
  </div>
<% end %>
如上所示,通过表单帮助方法定义输入框格式,其中付款方式选项列表中的属性使用模型层中提前定义的数组。
class Order < ActiveRecord::Base
  PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
 end
接下来就是按书中所说添加相应的CSS

/* Styles for order form */

.depot_form fieldset {
  background: #efe;
}

.depot_form legend {
  color: #dfd;
  background: #141;
  font-family: sans-serif;
  padding: 0.2em 1em;
}

.depot_form label {
  width: 5em;
  float: left;
  text-align: right;
  padding-top: 0.2em;
  margin-right: 0.1em;
  display: block;
}

.depot_form select, .depot_form textarea, .depot_form input {
  margin-left: 0.5em;
}

.depot_form .submit {
  margin-left: 4em;
}

.depot_form div {
  margin: 0.5em 0;
}

保护程序,在order模型层对表单传入的值进行判定

  validates :name, :address, :email, :pay_type, :presence => true
  validates :pay_type, :inclusion => PAYMENT_TYPES

页面效果如图:

2、获取订单细节

这部分的主要内容是填写订单页面中信息,将页面信息连同购物车中商品信息一同存入数据库中。

示意图如下:

                                             

首先根据订单与在线商品的关系分别定义其模型层文件

在线商品模型层:

class LineItem < ActiveRecord::Base
  belongs_to :order
  belongs_to :product
  belongs_to :cart

  def total_price
    product.price * quantity
  end
end
订单模型层:(指明订单被销毁时,从属于订单的在线商品也被销毁)
class Order < ActiveRecord::Base
  PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
  validates :name, :address, :email, :pay_type, :presence => true
  validates :pay_type, :inclusion => PAYMENT_TYPES
  has_many :line_items, :dependent => :destroy
end
最后,订单的create方法被定义如下:

a.用表单数据初始化新建的order对象

b.将购物车中的在线商品添加到order对象中

c.保存order对象

  def create
    @order = Order.new(params[:order])
    @order.add_line_items_from_cart(current_cart)

    respond_to do |format|
      if @order.save
        Cart.destroy(session[:cart_id])
        session[:cart_id] = nil
        format.html { redirect_to(store_url, :notice => 
          'Thank you for your order.') }
        format.xml  { render :xml => @order, :status => :created,
          :location => @order }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @order.errors,
          :status => :unprocessable_entity }
      end
    end
  end
将购物车中的在线商品添加到order对象中的方法定义在order的模型层文件中:

因为下一步要销毁购物车,为免于在线商品被同时销毁,在这一步将在线商品的cart_id设为nil。

同时将在线商品本身添加到订单的line_items集合中。

  def add_line_items_from_cart(cart)
    cart.line_items.each do |item|
      item.cart_id = nil
      line_items << item
    end
  end

到此为止,获取表单信息的任务完成,下面我们进行相关测试

必填项测试:


订单创建成功:


迭代G2:分页

分页是一个Web应用必不可少的功能,Rails中的分页可以借助于will_paginate插件实现。

1、修改Gemfile文件说明使用插件的意图(指明Rails的版本需要大于或等于3.0 pre)

gem 'will_paginate', '>= 3.0.pre'
修改完成之后使用bundle install命令来安装依赖

2、在script目录下创建文件用来生成测试数据

生成100个测试数据

Order.transaction do
  (1..100).each do |i|
    Order.create(:name => "Customer #{i}", :address => "#{i} Main Street",
      :email => "customer-#{i}@example.com", :pay_type => "Check")
  end
end
使用命令运行测试脚本:rails runner script/load_orders.rb
3、修改控制器以调用paginate插件

  def index
    @orders = Order.paginate :page=>params[:page], :order=>'created_at desc',
      :per_page => 10

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @orders }
    end
  end

4、在视图中增加链接

<h1>Listing orders</h1>

<table>
  <tr>
    <th>Name</th>
    <th>Address</th>
    <th>Email</th>
    <th>Pay type</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>

<% @orders.each do |order| %>
  <tr>
    <td><%= order.name %></td>
    <td><%= order.address %></td>
    <td><%= order.email %></td>
    <td><%= order.pay_type %></td>
    <td><%= link_to 'Show', order %></td>
    <td><%= link_to 'Edit', edit_order_path(order) %></td>
    <td><%= link_to 'Destroy', order, :confirm => 'Are you sure?',
              :method => :delete %></td>
  </tr>
<% end %>
</table>

<br />

<%= link_to 'New Order', new_order_path %>
<p><%= will_paginate @orders %></p>
展示效果如下:





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值