我有两个模型:Connection
和Membership
...它们之间有以下关联:
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
尽管有这些ID的memberships
记录,但可以在这里看到:
[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: "abc@test.com", 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: "def@test.com", 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
记录(为了不创建重复connection
记录)。
换句话说,每个connection
记录应与inviter_membership
和invited_membership
相对应。
现在,正在after_create :setup_connection
模型的Membership
回调上创建连接。因此,我尝试检查数据库中是否存在具有相关Connection
模型的membership
记录,然后只更新connection
记录,而不是创建新记录。
这就是为什么我的代码片段中的self
是一个membership
记录(因为我在运行时使用pry进行调试 - 即在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
答案 0 :(得分: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)
如果关联记录可能不存在(例如,Connection可能没有invite_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)