Rails 6 table 关联用户 table 与项目 table 关联

Rails 6 table association user table in association with items table

您好,我正在尝试创建一个包含用户正在销售的商品的应用。我有一个 table 用于销售商品的用户和一个 table 用于商品,但我对如何为买家设置下一个 table 感到有点困惑。我有一个单独的 table,它在用户和项目跟踪 user_id 和 item_id 之间是多对多的。我应该创建一个类似的 table 跟踪 buyer_id 和 item_id 吗?我希望能够跟踪从哪个用户那里购买了哪些商品,反之亦然。用户和买家来自同一用户 table.

谢谢!

编辑:

class UsersController < ApplicationController
  def my_page
    @user = current_user
    @seller_items = current_user.seller_orders.map { |so| so.order_items.map { |oi| { item: oi.item } } }.flatten
    @seller_items.to_a
  end
end

您确实需要中间的东西 - 这在电子商务中通常称为“订单”:

  • Link 给用户
  • Link 到项目

但也许还有更多属性:

  • 发售日期
  • 状态 (cart/order/paid/delivered)

所以确实 - 你会想要一个额外的模型

class Seller < ApplicationRecord
  belongs_to :user
  has_many selling_items
  has_many :items, through: :selling_items
end

class Buyer < ApplicationRecord
  belongs_to :user
  has_many bought_items
  has_many :items, through: :bought_items
end

class Items < ApplicationRecord
end

class BoughtItem < ApplicationRecord
  belongs_to :buyer
  belongs_to :item
end

class SellingItem < ApplicationRecord
  belongs_to :seller
  belongs_to :item
end

class User < ApplicationRecord
end

一个更完整的答案,更少的模型和命名连接。您可能希望“合并”订单表和 order_items 表,如果您处理的是单个待售商品,则删除多个表,例如汽车,但对于任何批量购买或可能与其他东西同时出售的东西,您可能需要这种布局:

生成模型:

rails g model User name:string
rails g model Item name:string
rails g model Order order_date:time status:string
rails g model OrderItem order:references item:references multiple:integer

修改create_order以添加附加参考:

  def change
    create_table :orders do |t|
      t.time :order_date, index: true, null: false
      t.string :status
      t.references :buyer, index: true, null: false, foreign_key: {to_table: :users}
      t.references :seller, index: true, null: false, foreign_key: {to_table: :users}

      t.timestamps
    end

迁移模型:

rake db:migrate
== 20201126090851 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0036s
== 20201126090851 CreateUsers: migrated (0.0039s) =============================

== 20201126090858 CreateItems: migrating ======================================
-- create_table(:items)
   -> 0.0030s
== 20201126090858 CreateItems: migrated (0.0032s) =============================

== 20201126091129 CreateOrders: migrating =====================================
-- create_table(:orders)
   -> 0.0077s
== 20201126091129 CreateOrders: migrated (0.0081s) ============================

== 20201126091209 CreateOrderItems: migrating =================================
-- create_table(:order_items)
   -> 0.0065s
== 20201126091209 CreateOrderItems: migrated (0.0067s) ========================

修改模型以添加连接:

app/models/user.rb
::::::::::::::
class User < ApplicationRecord
  has_many :buyer_orders, class_name: "Order", foreign_key: :buyer, inverse_of: :buyer
  has_many :seller_orders, class_name: "Order", foreign_key: :seller, inverse_of: :seller
end
::::::::::::::
app/models/item.rb
::::::::::::::
class Item < ApplicationRecord
  has_many :order_items, inverse_of: :item
end
::::::::::::::
app/models/order.rb
::::::::::::::
class Order < ApplicationRecord
  has_many :order_items, inverse_of: :order
  belongs_to :seller, class_name: "User", inverse_of: :seller_orders
  belongs_to :buyer, class_name: "User", inverse_of: :buyer_orders
end
::::::::::::::
app/models/order_item.rb
::::::::::::::
class OrderItem < ApplicationRecord
  belongs_to :order, inverse_of: :order_items
  belongs_to :item, inverse_of: :order_items
end

插入数据:

User.create(name: "hello")
User.create(name: "again")
Item.create(name: "whatever")
Order.create(buyer: User.first, seller: User.last, order_date: Time.now())
OrderItem.create(item: Item.first, order: Order.first, multiple: 1)

测试输出:

查看订单状态:

2.7.0 :002 > Order.first
   (0.5ms)  SELECT sqlite_version(*)
  Order Load (0.2ms)  SELECT "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT ?  [["LIMIT", 1]]
 => #<Order id: 1, order_date: "2000-01-01 09:26:22", status: nil, buyer_id: 1, seller_id: 2, created_at: "2020-11-26 09:26:22", updated_at: "2020-11-26 09:26:22">

2.7.0 :003 > Order.first.seller
  Order Load (0.2ms)  SELECT "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT ?  [["LIMIT", 1]]
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
 => #<User id: 2, name: "again", created_at: "2020-11-26 09:25:26", updated_at: "2020-11-26 09:25:26">

2.7.0 :004 > Order.first.buyer
  Order Load (0.2ms)  SELECT "orders".* FROM "orders" ORDER BY "orders"."id" ASC LIMIT ?  [["LIMIT", 1]]
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
 => #<User id: 1, name: "hello", created_at: "2020-11-26 09:25:18", updated_at: "2020-11-26 09:25:18">

查看第一个用户的“买家订单”:

2.7.0 :013 > User.first.buyer_orders
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
  Order Load (0.3ms)  SELECT "orders".* FROM "orders" WHERE "orders"."buyer_id" = ? LIMIT ?  [["buyer_id", 1], ["LIMIT", 11]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Order id: 1, order_date: "2000-01-01 09:26:22", status: nil, buyer_id: 1, seller_id: 2, created_at: "2020-11-26 09:26:22", updated_at: "2020-11-26 09:26:22">]>

查看第二个用户的“卖家订单”:

2.7.0 :014 > User.last.seller_orders
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
  Order Load (0.3ms)  SELECT "orders".* FROM "orders" WHERE "orders"."seller_id" = ? LIMIT ?  [["seller_id", 2], ["LIMIT", 11]]
 => #<ActiveRecord::Associations::CollectionProxy [#<Order id: 1, order_date: "2000-01-01 09:26:22", status: nil, buyer_id: 1, seller_id: 2, created_at: "2020-11-26 09:26:22", updated_at: "2020-11-26 09:26:22">]>

为了省心,请检查第一个用户没有任何卖家订单:

2.7.0 :015 > User.first.seller_orders
  User Load (0.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
  Order Load (0.2ms)  SELECT "orders".* FROM "orders" WHERE "orders"."seller_id" = ? LIMIT ?  [["seller_id", 1], ["LIMIT", 11]]
 => #<ActiveRecord::Associations::CollectionProxy []>
2.7.0 :016 >

控制器

class UsersController < ApplicationController
  def my_page
    @user = current_user
    @seller_orders = current_user.seller_orders
    # remember that you might want to filter this in the future
    # from_date = params[:from_date].present? ? params[:from_date] : Time.at(0)
    # to_date = params[:to_date].present? ? params[:to_date] : Time.now()
    # @seller_orders = @seller_orders.where(order_date: from_date..to_date)
  end
end

查看(我用的是haml)

%h1
  = @user.username
  Seller Orders

- @seller_orders.each do |so|
  %table.seller_order{id: "seller_order_#{so.id}"}
    %tr
      %th Order Date:
      %td= so.order_date
    %tr
      %th Buyer:
      %td= so.buyer.username
    %tr.spacer
      %td{colspan: 2} &nbsp;
    %tr
      %th Item
      %th Multiple
    - so.order_items.each do |oi|
      %tr
        %td= oi.item.name
        %td= oi.multiple

卖家商品

@seller_items = @seller_orders.map{|so| so.order_items.map{|oi| {multiple: oi.multiple, item: oi.item} }.flatten

或者可能(凭记忆写的,未经测试)

@seller_items = OrderItem.select("sum(order_items.multiple) as multiple, order_items.item_id as item_id").joins(:orders).joins(:buyer).where("users.id = ?", User.first.id).group("item_id")