2017-09-05 26 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라고 말하고, 사용자의 모델 연결은 has_many :owned_items, class_name: "Item"입니다. 내 이해에 따라 trades_received 메서드는 through: :owned_items이고 source: :trades은 이동 중에 외래 키 :wanted_item_id을 참조해야합니다. 그러나 그렇지 않습니다. item_id을 추가하기 위해 이전을 만들었지 만 Trade에서 두 항목이 필요하므로 두 개의 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' 연결로 이동합니다[email protected]는 내 설정이 Trade와 Item 사이에 직접적인 연결 고리가 없었기 때문에 발생한다고 제안했습니다. – sabaeus

+1

@sabaeus 데이터베이스 스키마 파일을 붙여 넣을 수 있습니다 – 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, .. 

레일이 작업을 자동으로 처리 할 수 ​​없습니다.

당신은 (당신이 앱에서 필요에 따라)이 단계 중 하나를 수행해야합니다

별도의 연결을해야하는 경우

:

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' 또는 무엇이든)과 직접적인 연결이 없기 때문에'많은 거래를 가질 수 없습니다. ' 따라서 협회를 분리해야합니다. 아이템에 대한 모든 거래를 선택하려면 수동으로 ('Trade.where ("wanted_item_id =? 또는 collateral_item_id =?", self.id') 수동으로 선택하거나 db 스키마를 변경해야합니다. – unkmas

+0

Ohhhh, 그래서 inverse_of 그 링크를 만들지? 와우, 마침내 의미가있다. 고마워! 나는 다른 것에 대해 혼란 스럽다. 수동 선택이 바람직하지 않거나 고통 스러울 수 있다고 말하는가? 나의 초기 게시물에 무역에 대한 여러 협회가 있지만 "모든 거래가 단일 협회로 필요한 경우"라고 대답 한 경우 – sabaeus