2017-09-05 38 views
3

我有一個關係模型,其中兩個用戶可以進入交易兩個項目交換。列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

回答

1

您正在設置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

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 

如果你需要的所有交易單的關聯:

那麼,你會有一個痛苦的屁股:)在這種情況下,你應該手動選擇關聯,或重新考慮你的數據模型。

+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