为什么列trades.item_id不存在?

时间:2017-09-05 00:37:33

标签: ruby-on-rails ruby postgresql has-many-through belongs-to

我有一个关系模型,其中两个用户可以进行交易以交换两个项目。

class User < ActiveRecord::Base
 has_many :owned_items, class_name: "Item"
 has_many :trades_received, class_name: "Trade", through: :owned_items, source: :trades
 has_many :trades
 has_many :wanted_items, class_name: "Item", through: :trades, source: :item
end

class Item < ActiveRecord::Base
 belongs_to :owner, class_name: "User", foreign_key: :user_id
 has_many :trades, dependent: :destroy
 has_many :trade_requesters, through: :trades
 has_many :trade_recipients, through: :trades
end

class Trade < ActiveRecord::Base
 belongs_to :trade_requester, class_name: "User"
 belongs_to :trade_recipient, class_name: "User"
 belongs_to :wanted_item, class_name: "Item", foreign_key: :wanted_item_id
 belongs_to :collateral_item, class_name: "Item", foreign_key: :collateral_item_id
end

我的Trades表上的迁移如下所示:

create_table :trades do |t|
 t.belongs_to :trade_requester
 t.belongs_to :trade_recipient
 t.belongs_to :wanted_item
 t.belongs_to :collateral_item
end

堆栈跟踪导致我用来列出所有交易请求的帮助方法。该行显示@trades = current_user.trades_received.requested.count,然后显示为用户has_many :owned_items, class_name: "Item"上的模型关联。根据我的理解,trades_received方法(称为through: :owned_itemssource: :trades应该在迁移中引用:wanted_item_id外键。但事实并非如此。如果我创建迁移以添加item_id,但是交易需要两个项目,那么它就可以工作,因此我将其拆分为两个wanted_itemcollateral_item关联。如何设置用户关联以便它引用另一个用户请求的项目?项目has_many :trades应该是我拥有的方式还是项目belongs_to :trades

完整错误:

PG::UndefinedColumn: ERROR:  column trades.item_id does not exist
LINE 1: ...LECT COUNT(*) FROM "trades" INNER JOIN "items" ON "trades"."...
                                                         ^
: SELECT COUNT(*) FROM "trades" INNER JOIN "items" ON "trades"."item_id" = "items"."id" WHERE "items"."user_id" = $1 AND "trades"."approved" IS NULL

tldr:我需要跟踪一堆复杂的has_many :through关联,我不认为我的数据模型是正确的,需要帮助理解原因。谢谢。

2 个答案:

答案 0 :(得分:1)

好的,好吧。问题出在这里:

has_many :trades, dependent: :destroy

Trade模型中:

belongs_to :wanted_item, ...
belongs_to :collateral_item, ..

Rails无法自动处理此问题。

您需要执行以下步骤之一(取决于您在应用中需要的内容):

如果您需要单独的关联:

class User < ActiveRecord::Base
  has_many :trades_received, class_name: "Trade", through: :owned_items, source: :wantable_trades
end

class Item < ActiveRecord::Base
  has_many :wanted_trades, class_name: 'Trade', inverse_of: :wanted_item, dependent: :destroy
  has_many :collateral_trades, class_name: 'Trade', inverse_of: :collateral_item, dependent: :destroy
end

如果您需要所有交易作为单一关联:

好吧,你会痛苦的屁股:)在这种情况下你应该手动选择关联,或重新考虑你的数据模型。

答案 1 :(得分:1)

您在has_many :throughUser之间设置了两个Item关系,Trade作为两者的联接表。你有一些困惑的关系。以下是基于迁移的设置:

class User < ActiveRecord::Base
 has_many :received_trades, class_name: "Trade", foreign_key: "trade_recipient"
 has_many :requested_trades, class_name: "Trade", foreign_key: "trade_requester"
 has_many :collateral_items, through: :received_trades
 has_many :wanted_items, through: :requested_trades
end

class Item < ActiveRecord::Base
 has_many :collateral_items, class_name: "Trade", foreign_key: "collateral_item"
 has_many :wanted_items, class_name: "Trade", foreign_key: "wanted_item"
 has_many :trade_requesters, through: :wanted_items
 has_many :trade_recipients, through: :collateral_items
end

class Trade < ActiveRecord::Base
 belongs_to :trade_requester, class_name: "User"
 belongs_to :trade_recipient, class_name: "User"
 belongs_to :wanted_item, class_name: "Item"
 belongs_to :collateral_item, class_name: "Item"
end

##migration
create_table :trades do |t|
 t.belongs_to :trade_requester
 t.belongs_to :trade_recipient
 t.belongs_to :wanted_item
 t.belongs_to :collateral_item
end

一些解释:

Item has_many :collateral_item  ## item_id in table collateral_items
Item has_many :collateral_item, class_name: "Trade", foreign_key: "collateral_item"
##collateral_item_id in trades table.