美文网首页ruby on rails
关系: order 和 Product 分析.md

关系: order 和 Product 分析.md

作者: 栋栋晓 | 来源:发表于2016-03-28 03:01 被阅读75次

    1.0 4 张表

    表1: products : name | price | active
    表2: orders : subtotal | tax | shipping | total | order_status(references)
    表3: order_items : product_id(references) | order_id(references) | unit_price | total_price | quantity
    表4: order_status : name
    

    2.0 表的关系

    product <----belongs_to/has_many-----> order_item <----has_many/belongs_to-----> order
    

    多对多关系一般不会用 has_and_belongs_to_many, 而是使用has_many :through 第三张表关联

    order <-----belongs_to/has_many-----> order_status
    

    models

    1.0

    rails g model Product name 'price:decimal{12,3}' active:boolean
    rails g model OrderStatus name:string
    rails g model Order 'subtotal:decimal{12,3}' 'tax:decimal{12,3}' 'shipping:decimal{12,3}' 'total:decimal{12,3}' order_status:references
    rails g model OrderItem product:references order:references 'unit_price:decimal{12,3}' quantity:integer 'total_price:decimal{12,3}'
    rake db:migrate
    

    2.0

    app/models/order.rb:
    
    class Order < ActiveRecord::Base
      belongs_to :order_status
      has_many :order_items
      before_create :set_order_status
      before_save :update_subtotal
    
      def subtotal
        order_items.collect { |oi| oi.valid? ? (oi.quantity * oi.unit_price) : 0 }.sum
      end
    private
      def set_order_status
        self.order_status_id = 1
      end
    
      def update_subtotal
        self[:subtotal] = subtotal
      end
    end
    
    app/models/order_item.rb:
    
    class OrderItem < ActiveRecord::Base
      belongs_to :product
      belongs_to :order
    
      validates :quantity, presence: true, numericality: { only_integer: true, greater_than: 0 }
      validate :product_present
      validate :order_present
    
      before_save :finalize
    
      def unit_price
        if persisted?
          self[:unit_price]
        else
          product.price
        end
      end
    
      def total_price
        unit_price * quantity
      end
    
    private
      def product_present
        if product.nil?
          errors.add(:product, "is not valid or is not active.")
        end
      end
    
      def order_present
        if order.nil?
          errors.add(:order, "is not a valid order.")
        end
      end
    
      def finalize
        self[:unit_price] = unit_price
        self[:total_price] = quantity * self[:unit_price]
      end
    end
    
    app/models/order_status.rb:
    
    class OrderStatus < ActiveRecord::Base
      has_many :orders
    end
    
    app/models/product.rb:
    
    class Product < ActiveRecord::Base
      has_many :order_items
    
      default_scope { where(active: true) }
    end
    

    controllers

    rails g controller Products index
    rails g controller Carts show
    rails g controller OrderItems create update destroy
    
    app/controllers/application_controller.rb:
    
    class ApplicationController < ActionController::Base
      protect_from_forgery with: :exception
      helper_method :current_order
    
      def current_order
        if !session[:order_id].nil?
          Order.find(session[:order_id])
        else
          Order.new
        end
      end
    end
    
    app/controllers/carts_controller.rb:
    
    class CartsController < ApplicationController
      def show
        @order_items = current_order.order_items
      end
    end
    
    app/controllers/order_items_controller.rb:
    
    class OrderItemsController < ApplicationController
      def create
        @order = current_order
        @order_item = @order.order_items.new(order_item_params)
        @order.save
        session[:order_id] = @order.id
      end
    
      def update
        @order = current_order
        @order_item = @order.order_items.find(params[:id])
        @order_item.update_attributes(order_item_params)
        @order_items = @order.order_items
      end
    
      def destroy
        @order = current_order
        @order_item = @order.order_items.find(params[:id])
        @order_item.destroy
        @order_items = @order.order_items
      end
    private
      def order_item_params
        params.require(:order_item).permit(:quantity, :product_id)
      end
    end
    
    app/controllers/products_controller.rb:
    
    class ProductsController < ApplicationController
      def index
        @products = Product.all
        @order_item = current_order.order_items.new
      end
    end
    

    routes.rb:

    Rails.application.routes.draw do
      resources :products, only: [:index]
      resource :cart, only: [:show]
      resources :order_items, only: [:create, :update, :destroy]
      root to: "products#index"
    end
    

    相关文章

      网友评论

        本文标题:关系: order 和 Product 分析.md

        本文链接:https://www.haomeiwen.com/subject/gvjjlttx.html