列trades.item_id为什么不存在?

问题描述:

我有一个关系模型,其中两个用户可以进入交易两个项目交换。列trades.item_id为什么不存在?

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 

迁移我的交易表看起来像这样:

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,然后放到模型关联的User上,其中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协会,我不认为我的数据模型是正确的,需要帮助理解为什么。谢谢。

+0

'用户的has_many:trades_received'。所以它应该是'current_user.trades_receiveds'。可能更好地将其更改为'received_trades'。你的'#requested'方法是什么?哪条确切的线给你的错误? – EJ2015

+0

'requested'是一个范围,它只是'scope:requested, - > {where(approved:nil)}'。我的错误来自于我在头文件中使用的帮助器,并且涉及用户模型的':trades_received'关联。@unkmas认为这是由于我的设置在Trade和Item之间没有直接联系。 – sabaeus

+1

@sabaeus可以粘贴数据库schema文件 – krishnar

您正在设置UserItem之间的两个has_many :through关系,并将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. 
+0

谢谢你,这是有道理的。问题虽然:我认为foreign_keys只应该在关系的'belongs_to'一侧? – sabaeus

+1

'has_many'和'belongs_to'都有'foreign_key'选项。当外键不遵循ActiveRecord约定(即关联名称+“_id”)时使用它,这里的'has_many'关系就是这种情况。 – EJ2015

+0

但是我为什么要把它放在另一边呢? – sabaeus

好吧,好吧。问题就在这里:

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 

如果你需要的所有交易单的关联:

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

+0

你是指“手动选择关联还是重新考虑数据模型?” ':wanted_trades'和':trades_received'不是单独的关联吗?另外,为什么在Item模型中有两次':wanted_trades'?那不就是两次引用同一个项目吗? – sabaeus

+1

@sabaeus对不起,我不小心丢弃了编辑。更新了我的答案。 物品不能只是“有很多交易”,因为从贸易到物品('item_id'或其他)没有直接的联系。所以你必须分开关联。如果要选择,你必须手动SELCT他们项目的所有行业('Trade.where(“wanted_item_id =?或collat​​eral_item_id =?”,self.id')或改变你的数据库架构。 – unkmas

+0

天上,等等'inverse_of '创建链接?哇,终于是有道理的。谢谢!我很困惑的另一问题,虽然。你是说手动选择是不妥当的,或可能是一个痛苦?我只问,因为我最初的职位有多个关联贸易,但你的回答说:“如果你需要的所有交易作为一个单一的协会” – sabaeus