物品-订单联接表,难以理解的餐馆应用代码

时间:2018-08-28 16:48:49

标签: ruby-on-rails ruby postgresql

我正在研究饭店应用的代码。我现在被困住了,我不了解订单和项目之间的关系。看起来有一个联合表,但我不了解它的逻辑。这是模式的代码`

ActiveRecord::Schema.define(version: 20160327212111) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "items", force: :cascade do |t|
    t.string  "name"
    t.string  "cuisine_type"
    t.integer "price"
  end

  create_table "items_orders", id: false, force: :cascade do |t|
    t.integer "order_id", null: false
    t.integer "item_id",  null: false
  end

  add_index "items_orders", ["item_id", "order_id"], name: "index_items_orders_on_item_id_and_order_id", using: :btree
  add_index "items_orders", ["order_id", "item_id"], name: "index_items_orders_on_order_id_and_item_id", using: :btree

  create_table "orders", force: :cascade do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "party_id"
    t.boolean  "paid?",      default: false
  end
    end

在这里,控制器命令的创建方法使我更加困惑。

  def create
    food_items = params[:item][:item_id].drop(1).map{ |item| item.to_i}
    @items = Item.where("id in (?)", food_items)
    @order = Order.new(order_params)
      # items_array = params[:item]["item_id"].drop(1)

    if @order.save
        @items.each { |item| @order.items << item }
        redirect_to orders_path
    else
      redirect_to new_order_path
    end
  end

谢谢您的帮助。

商品和订单的更新模型

    class Item < ActiveRecord::Base
  has_and_belongs_to_many :orders
end

    class Order < ActiveRecord::Base
  has_and_belongs_to_many :items
  has_one :party

end

物品和订单控制器

    class ItemsController < ApplicationController

  def index
    @item = Item.all
  end

  def show
    @item = Item.find(params[:id])
  end

  def new
    @item = Item.new
  end

  def create
    @item = Item.new(item_params)
    if @item.save
    redirect_to items_path
    else
    redirect_to new_item_path
  end

  end

  def edit
    @item = Item.find(params[:id])
  end

  def update
    @item = Item.find(params[:id])
    @item.update(item_params)
    redirect_to items_path
  end

  def destroy
    @item = Item.find(params[:id])
    @item.destroy
    redirect_to items_path
  end

  private

  def item_params
    params.require(:item).permit(:name, :cuisine_type, :price)
  end


end

    class OrdersController < ApplicationController

  def index
    @orders = Order.order(:party_id)
    @items = Item.all
    @parties = Party.all
  end

  def show
    @orders = Order.find(params[:id])
  end

  def new
    @order = Order.new
    @orders = Order.all
    @items = Item.all
    @parties = Party.all
  end

  def create
    puts "Item ids #{params[:item][:item_id]}"
    food_items = params[:item][:item_id].drop(1).map{ |item| item.to_i}
    @items = Item.where("id in (?)", food_items)
    @order = Order.new(order_params)
      # items_array = params[:item]["item_id"].drop(1)
    if @order.save
        @items.each { |item|
          @order.items << item
        }
        redirect_to orders_path
    else
      redirect_to new_order_path
    end
  end

  def destroy
    @order = Order.find(params[:id])
    @order.destroy
    redirect_to orders_path
  end


  private
  def order_params
    params.require(:order).permit(:party_id, :item_id)
  end

end

1 个答案:

答案 0 :(得分:0)

根据您的架构,您必须在OrderItem类之间建立has-and-belongs-to-many关联。

免责声明: It can easily be has-many-through关联而不是HABTM,但在联接表 items_orders 中没有看到任何多余的列。同样,您也没有提到ItemsOrder模型的任何特殊用途(如果存在)。因此,我将使用简单的HABTM。

型号:

class Order
  has_and_belongs_to_many :items
end

class Item
  has_and_belongs_to_many :orders
end

有了这些关联,您可以执行以下操作:

# Say, you have some items in your database
item = Item.take
 => #<Item id: 1>

Order.count
 => 0

# Create a new order and assign `item` to it
order = Order.new
order.items << item
order.save!

以上语句集将在连接表中插入一条新记录,如下所示:

| id | order_id | item_id |
| 1  | 1        | 1       |

现在,您可以按以下顺序检查订单中显示的商品:

order.items
 => [#<Item id: 1>, ...]

或相反:

item.orders
 => [#<Order id: 1>, ...]

现在,让我们浏览一下控制器代码:

def create
  # I don't know what `params[:item][:item_id]` contains, but `drop` method drops the first n (in this case, 1) number of elements and returns the remaining array
  # ... and map is changing each element from whatever format to integer format
  # Read more:
  #   - https://apidock.com/ruby/Array/drop
  #   - https://apidock.com/ruby/Array/map
  food_items = params[:item][:item_id].drop(1).map { |item| item.to_i }

  # Searching for items with ID ANY IN given array of IDs
  @items = Item.where("id in (?)", food_items)

  # Initialize a new order with permitted params (hopefully). Check definition of `order_params `
  @order = Order.new(order_params)

  if @order.save
    # Assigning each searched item to new order, which will create as many new records in join table as the number of `@items`
    @items.each { |item| @order.items << item }

    # The usual
    redirect_to orders_path
  else
    # Shouldn't it be render, and not redirect
    redirect_to new_order_path
  end
end

希望有帮助。