?
原文?
概述
订单更新绝大多数是控制订单状态的改变.在此,我将订单状态抽象成点(order_status),改变订单状态的方法称为operation,operation不直接与订单相关,只与order_status相关.
?
?
当订单状态发生改变时,订单包含的操作便自然变更为新的可执行操作
?
样例
以下是一个电商网站的状态流转图
??
?
我是这样做模型层的
class="ruby" name="code">class Order < ActiveRecord::Base belongs_to :order_status has_many :operations, through: :order_status def do operation, &block return 'No method match' unless operations.find_by(name: operation) block_given? ? send(operation, &block) : set_order_status(send(operation)) end # 提醒买家,订单将要被自动确认收货,如果尚未到货,请点击延长收货时间 # email或者短信 def message_notice end private # 用户支付货款至my_site def pay_my_site &block set_order_status order_status.do __method__.to_s and save "#{yield}?target_uuid=#{uuid}&target_type=trade&amount=#{payment_amount}&paid_by=#{payment_way.name}&foo_type=Order" if block_given?#根据block返回一个支付页面 end # 取消订单 def cancel order_status.do __method__.to_s end # 系统自动取消订单 def auto_cancel order_status.do __method__.to_s if operations.find_by(name: operation) end # 确认到款 def payment_receive order_status.do __method__.to_s if spill? end # 取消并退款 def cancel_with_refund refund_money order_status.do __method__.to_s end # 发货 def shipping delay(run_at: 3.day.from_now).message_notice set_received_at and order_status.do __method__.to_s end # 退款 def refund refund_money order_status.do __method__.to_s end # 确认收货 def receive order_status.do __method__.to_s end # 延长收货时间 def extend_time update_attribute :received_at, received_at + 7.days.from_now order_status.do __method__.to_s end # 到期自动确认收货(默认7天) def auto_receive order_status.do __method__.to_s end # 退货/换货 def return_goods order_status.do __method__.to_s end end
?
?
class OrderStatus < ActiveRecord::Base has_many :operations def do operation operations.find_by(name: operation).do_operation end end
?
?
class Operation < ActiveRecord::Base belongs_to :order_status belongs_to :result, class_name: :OrderStatus def do_operation result end end
?
?
简单的状态变迁列表
?
?
我的初始化脚本(rake)
?
?
#encoding: utf-8 namespace :order_status do task init: :environment do Operation.delete_all File.open(File.expand_path('../../../docs/order_status', __FILE__)).each_line do |line| arr = line.split(/[\t\n]+/).first(7) order_status = OrderStatus.find_by name: arr[1] order_status = OrderStatus.create(name: arr[1]) if order_status.blank? result = OrderStatus.find_by name: arr[5] result = OrderStatus.create(name: arr[5]) if result.blank? Operation.create({ name: arr[3], order_status: order_status, result: result, operator: arr[6] }) end end end
?
?
?
?
控制器是这样设计的
?
?
class CartsController < ApplicationController before_action :set_order, only: [:to_pay_page, :operate_by_buyer, :operate_by_seller, :buyer_operations,:seller_operations] # redirect_to pay_page # params: :id => order.id, :payment_name => 'alipay' # 需检测是否已经选择了支付方式 def to_pay_page @order.payment_way = BasicSettings::PaymentWay.find_by name: params[:payment_name] pay_params = Proc.new {url = '/pays/pay'} redirect_to @order.do('pay_my_site', &pay_params) end # 买家操作 # params: order.id, operation def operate_by_buyer if params[:operation] == 'pay_my_site' return redirect_to select_payment_carts_path(id: @order.id) end @order.do params[:operation] if @order.operations.find_by(operator: 'buyer', name: params[:operation]) redirect_to controller: 'my/orders', action: 'index' end # 卖家操作 # params: order.id, operation def operate_by_seller @order.do params[:operation] if @order.operations.find_by(operator: 'seller', name: params[:operation]) redirect_to controller: params[:controller], action: params[:action] end # 买家可执行的操作 def buyer_operations render json: @order.operations.where(operator: 'buyer').collect{|t|t.name}.to_json end # 卖家可执行的操作 def seller_operations render json: @order.operations.where(operator: 'seller').collect{|t|t.name}.to_json end private def set_order @order = Slms::Order.find_by id: params[:id] end end
?
?
?
?
至此基本完工
?
注: 为了便于开发,order_status和operation都存在数据库中,部署生产环境时需缓存
网友 2014/9/2 12:58:22 发表
连排版都没做,你对得起作者么