qua*_*ato 9 postgresql activerecord ruby-on-rails
我正在建立一个约会风格的应用程序,其中User
s可以批准其他用户.我使用Approval
模型来跟踪这些关系.每个Approval
都有一个user_id
和一个approved_id
- 批准的用户ID User
.它还有rejected_at
一个日期时间,表示一个User
人拒绝了另一个人.
要向符合条件的用户提供current_user
,我必须查询其中任何一个的用户
Approval
关系Approval
关系只与approved_id
as current_user.id
(意味着符合条件的用户批准current_user但反过来没有任何关系)User
具有Approval
非nil rejected_at
属性的s,其中approved_id
是User
或者user_id
是current_user
.如何创建ActiveRecord查询以查找符合条件的用户?我知道我可以做joins
的Approval
,但我也想考虑那里是没有Approval
关系的User
小号!我认为只做两个单独的查询可能更有意义,但我想知道是否可以组合成一个...
您想要的行为是LEFT OUTER JOIN,它将包括来自users
是否存在任何匹配行的行approvals
.这样,你得到一个User
没有发表Approval
关于你的目标的人User
,或者一个已经发布并且我们可以过滤拒绝的人.
查询看起来像
-- Looking for users who either have no opinion or have approved user 1
SELECT *
FROM users
LEFT OUTER JOIN approvals
ON users.id = approvals.user_id
AND approvals.approved_id = 1 -- Filter for only approvals of user 1
WHERE users.id != 1 -- Ignore user 1
AND (
approvals.approved_id IS NULL -- Approving user has no opinion of user 1
OR approvals.rejected_at IS NULL -- Approving user has not rejected user 1
)
;
Run Code Online (Sandbox Code Playgroud)
碎片,
users LEFT OUTER JOIN approvals
考虑所有users
,即使他们没有approvals
ON users.id = approvals.user_id
users
与approvals
他们创造的对ON ... AND approvals.approved_id = 1
只考虑approvals
了User 1
WHERE users.id != 1
只考虑其他 users
WHERE ... approvals.approved_id IS NULL
采用users
的是没有创造任何approvals
有关User 1
.WHERE ... approvals.rejected_at IS NULL
需要users
的是做创建Approval
了User 1
,这是不是一个拒绝ActiveRecord
当我们翻译它时,它没有做任何特别漂亮的事情,但它有效:
class User < ActiveRecord::Base
def eligible_partners
User.joins( # Join like we did before
<<-SQL
LEFT OUTER JOIN approvals
ON users.id = approvals.user_id
AND approvals.approved_id = #{self.id}
SQL
).where.not(id: id) # Ignore ourselves
.where( # Filter for no approvals or a positive approval
<<-SQL
approvals.approved_id IS NULL
OR approvals.rejected_at IS NULL
SQL
)
end
end
Run Code Online (Sandbox Code Playgroud)
如果你想要更具可读性的东西,你可以收集每个User
拒绝给定人的ID ,然后获得所有其他User
的ID .一方面,这是两个问题; 另一方面,它可能比JOIN
你的桌子变大后便宜,而且它更容易理解.
def other_eligible_partners
rejecter_ids = Approval
.where(approved_id: id) # About ourselves
.where.not(rejected_at: nil) # Rejected us
.pluck(:user_id)
User.where.not(id: rejecter_ids + [id]) # People who didn't reject us
end
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
126 次 |
最近记录: |