2015-12-01 57 views
0

我有兩個型號:ConnectionMembership ...其間具有以下關聯:如何在關聯的列上執行where子句?

class Membership < ActiveRecord::Base 
    belongs_to :inviter, class_name: "User", foreign_key: "user_id" 
    belongs_to :invited, class_name: "User", foreign_key: "invited_id" 
    has_many :connections, dependent: :destroy 
end 

class Connection < ActiveRecord::Base 
    belongs_to :inviter_membership, class_name: "Membership", foreign_key: "membership_id" 
    belongs_to :invited_membership, class_name: "Membership", foreign_key: "invited_membership_id"  
end 

這裏有兩個membership對象:

[34] pry(#<Membership>)> self 
=> #<Membership id: 54, family_tree_id: 43, user_id: 41, created_at: "2015-12-01 00:40:37", updated_at: "2015-12-01 00:40:37", relation: "wife", member_id: nil, invited_id: 1, relative_type: 0> 
[35] pry(#<Membership>)> mem 
=> #<Membership id: 53, family_tree_id: 1, user_id: 1, created_at: "2015-12-01 00:39:58", updated_at: "2015-12-01 00:40:37", relation: "husband", member_id: nil, invited_id: 41, relative_type: 0> 
[39] pry(#<Membership>)> self.invited_id 
=> 1 

然後,我有一個connection對象:

[36] pry(#<Membership>)> c 
=> #<Connection id: 38, membership_id: 53, sent_at: "2015-12-01 00:40:14", responded_at: nil, send_limit: nil, times_sent: 1, removed_at: nil, created_at: "2015-12-01 00:40:14", updated_at: "2015-12-01 00:40:14", request_status: 0, invited_membership_id: nil> 

如何查找所有connection記錄,即有membership.invited_id = 41(或某些值)?

換句話說,我願做這樣的事情:

Connection.where("membership.invited_id = ? OR invited_membership.invited_id = ?", self.id, self.id).exists? 

但是,當我嘗試了上面,我得到這個錯誤:

[138] pry(main)> Connection.where("membership.invited_id = ? OR invited_membership.invited_id = ?", 41, 41).exists? 
    Connection Exists (165.3ms) SELECT 1 AS one FROM "connections" WHERE (membership.invited_id = 41 OR invited_membership.invited_id = 41) LIMIT 1 
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "membership" 
LINE 1: SELECT 1 AS one FROM "connections" WHERE (membership.invit... 

那麼,如何運行where查詢以將相關記錄的列與我提供的參數進行匹配?

編輯1

基於美妙建議從@messanjah我幾乎沒有。這是我使用的查詢:

Connection.joins(:inviter_membership, :invited_membership). 
     where("memberships.invited_id = ? OR invited_memberships_connections.invited_id = ? OR memberships.user_id = ? OR invited_memberships_connections.user_id = ?", self.inviter.try(:id), self.inviter.try(:id), self.invited.try(:id), self.invited.try(:id)).exists? 

哪裏self是這樣的:

[22] pry(#<Membership>)> self 
=> #<Membership id: 69, family_tree_id: 49, user_id: 47, created_at: "2015-12-01 04:53:17", updated_at: "2015-12-01 04:53:17", relation: "wife", member_id: nil, invited_id: 1, relative_type: 0> 

但是當我運行該查詢,它返回一個空數組或false

[14] pry(#<Membership>)> connection_exists 
    CACHE (0.0ms) SELECT 1 AS one FROM "connections" INNER JOIN "memberships" ON "memberships"."id" = "connections"."membership_id" INNER JOIN "memberships" "invited_memberships_connections" ON "invited_memberships_connections"."id" = "connections"."invited_membership_id" WHERE (memberships.invited_id = 47 OR invited_memberships_connections.invited_id = 47 OR memberships.user_id = 1 OR invited_memberships_connections.user_id = 1) LIMIT 1 
=> false 

儘管事實上有一個memberships與這些ID記錄,可以在這裏看到:

[24] pry(#<Membership>)> c 
=> #<Connection id: 49, membership_id: 68, sent_at: "2015-12-01 04:52:51", responded_at: nil, send_limit: nil, times_sent: 1, removed_at: nil, created_at: "2015-12-01 04:52:51", updated_at: "2015-12-01 04:52:51", request_status: 0, invited_membership_id: nil> 
[25] pry(#<Membership>)> c.inviter_membership 
=> #<Membership id: 68, family_tree_id: 1, user_id: 1, created_at: "2015-12-01 04:52:32", updated_at: "2015-12-01 04:53:17", relation: "husband", member_id: nil, invited_id: 47, relative_type: 0> 
[26] pry(#<Membership>)> c.invited_membership 
=> nil 
[27] pry(#<Membership>)> c.inviter_membership.invited_id 
=> 47 
[28] pry(#<Membership>)> c.inviter_membership.user_id 
=> 1 

請注意在最後兩個查詢中返回IDs,但是當傳遞給主查詢時,我運行它返回空。

這可能是什麼原因造成的?

編輯2

這是新的代碼,我想:

Connection.joins("LEFT JOIN memberships inviter_memberships ON inviter_memberships.id = connections.membership_id"). 
    joins("LEFT JOIN memberships invited_memberships ON invited_memberships.id = connections.invited_membership_id"). 
    where("inviter_memberships.invited_id = ? OR invited_memberships.invited_id = ? 
    OR inviter_memberships.user_id = ? OR invited_memberships.user_id = ?", self.invited.try(:id), self.invited.try(:id), self.inviter.try(:id), self.inviter.try(:id)).exists? 

其中self是:

[15] pry(#<Membership>)> self 
=> #<Membership id: 71, family_tree_id: 50, user_id: 48, created_at: "2015-12-01 05:46:00", updated_at: "2015-12-01 05:46:00", relation: "wife", member_id: nil, invited_id: 1, relative_type: 0> 
[20] pry(#<Membership>)> self.invited 
=> #<User id: 1, email: "[email protected]", encrypted_password: "$2a$10$IQXTVqZmMaUUv4WZlwXze.OTfWki2d2qZEjj01isCZZ...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 7, current_sign_in_at: "2015-09-25 09:35:43", last_sign_in_at: "2015-09-25 01:36:10", current_sign_in_ip: "127.0.0.1", last_sign_in_ip: "192.168.1.106", created_at: "2015-07-25 02:20:15", updated_at: "2015-09-25 09:35:43", first_name: "Marc", confirmation_token: nil, confirmed_at: "2015-07-25 02:20:16", confirmation_sent_at: "2015-07-25 02:20:16", unconfirmed_email: nil, invitation_relation: nil, avatar: "Me-Bio-Pic.jpg", invitation_token: nil, invitation_created_at: nil, invitation_sent_at: nil, invitation_accepted_at: nil, invitation_limit: nil, invited_by_id: nil, invited_by_type: nil, invitations_count: 0, bio: "I am Marc Gayle. I build things and I love my fami...", last_name: "Gayle", gender: 0, birthday: nil> 
[21] pry(#<Membership>)> self.inviter 
=> #<User id: 48, email: "[email protected]", encrypted_password: "", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2015-12-01 05:40:45", updated_at: "2015-12-01 05:40:45", first_name: "Cheyenne-Kari", confirmation_token: nil, confirmed_at: nil, confirmation_sent_at: nil, unconfirmed_email: nil, invitation_relation: "husband", avatar: nil, invitation_token: "D8uPGyxAeX95kfYGxRq-", invitation_created_at: "2015-12-01 05:40:45", invitation_sent_at: "2015-12-01 05:40:45", invitation_accepted_at: nil, invitation_limit: nil, invited_by_id: 1, invited_by_type: "User", invitations_count: 0, bio: nil, last_name: "Gayle", gender: 1, birthday: nil> 

基本上什麼,我試圖做的是試圖發現是否存在connection記錄,用於記錄我將要創建的相關membership記錄(努力嘗試n ot創建一個重複的connection記錄)。

換句話說,每個connection記錄應該對應於inviter_membershipinvited_membership

現在,在Membership模型上的after_create :setup_connection回調上創建連接。因此,我正在檢查數據庫中的Connection記錄,該記錄包含相關的membership型號,然後只更新該記錄,而不是創建新記錄。

所以這就是爲什麼在我的代碼片段的self,是membership記錄(因爲我在運行時用撬調試 - 即after_create調用後,新connection記錄之前已創建)。

我希望這有助於澄清我正在嘗試做什麼。如果不是,我可以再解釋一些。

編輯3

下面是執行LEFT JOIN SQL我上面做的服務器日誌:

[1] pry(#<Membership>)> connection_exists 
    CACHE (0.0ms) SELECT 1 AS one FROM "connections" LEFT JOIN memberships inviter_memberships ON inviter_memberships.id = connections.membership_id LEFT JOIN memberships invited_memberships ON invited_memberships.id = connections.invited_membership_id WHERE (inviter_memberships.invited_id = 1 OR invited_memberships.invited_id = 1 
     OR inviter_memberships.user_id = 51 OR invited_memberships.user_id = 51) LIMIT 1 
=> false 

回答

2

您可以在協會的加入,包括在where其列。

Connection.joins(:inviter_membership, :invited_membership). 
    where("memberships.invited_id = ? OR invited_memberships_connections.invited_id = ?", self.id, self.id) 

這有點尷尬,因爲表別名不明顯(我使用的是Rails 4.2.3,YMMV)。

您不妨構建聯接明確,用於在查詢更大的控制權:

Connection. 
    joins("INNER JOIN memberships inviter_memberships ON inviter_memberships.id = connections.inviter_membership_id"). 
    joins("INNER JOIN memberships invited_memberships ON invited_memberships.id = connections.invited_membership_id"). 
    where("inviter_memberships.invited_id = ? 
     OR invited_memberships.invited_id = ?", self.id, self.id) 

如果的關聯記錄可能不存在(例如,連接可能不具有invited_membership),使用LEFT加入以避免拋出。

Connection. 
    joins("LEFT JOIN memberships inviter_memberships ON inviter_memberships.id = connections.inviter_membership_id"). 
    joins("LEFT JOIN memberships invited_memberships ON invited_memberships.id = connections.invited_membership_id"). 
    where("inviter_memberships.invited_id = ? 
     OR invited_memberships.invited_id = ?", self.id, self.id) 
+0

完美...這正是我所期待的。非常感謝! – marcamillion

+0

幾乎完美:) - 查看更新的問題,更詳細地介紹了@messanjah的細節。 – marcamillion

+0

INNER聯盟中的一個可能會拋出你想要的記錄。切換到左連接。 – messanjah

相關問題