我已经建模,用户在活动中出席了会议.
但这似乎是可怕的语法,令人困惑. @H_502_4@2)使用包括 @H_502_4@如果我使用include而不是join,我不会得到重复加入.由于它分开加载事件,并且足够聪明,无法重复.
最合乎逻辑的
user.events.is_attending是我最理想的用途. @H_502_4@2)有没有办法告诉活动记录忽略连接,如果他们已经发生了?
class User has_many :attendances has_many :events,through: :attendances class Event has_many :attendances scope :is_attending,-> { joins(:attendances).where(attendances:{attend_status: Attendance.attend_statuses[:attending] })} class Attendance belongs_to :event belongs_to :user enum attend_status: { attending: 0,not_attending: 1}@H_502_4@我的问题是关于范围查询和最佳实践. @H_502_4@我把大部分的范围查询都放在了Event上. @H_502_4@我想获取att_status = 0的特定用户的所有事件
user = User.find(...) user.events.is_attending@H_502_4@逻辑上我会想,这是最好的,最有意义 @H_502_4@不过这会给我一个双重的内在联系
SELECT "events".* FROM "events" INNER JOIN "attendances" "attendances_events" ON "attendances_events"."event_id" = "events"."id" INNER JOIN "attendances" ON "events"."id" = "attendances"."event_id" WHERE "attendances"."user_id" = $1 AND "attendances"."attend_status" = 0@H_502_4@显然这会创造出不是我想要的重复项. @H_502_4@所以选择我知道我可以做 @H_502_4@1)使用合并
Event scope :for_user,-> (user){ joins(:attendances).where(attendances: {user: user})}@H_502_4@然后打电话
Event.for_user(user).merge(Event.is_attending)@H_502_4@这给了我sql
SELECT "events".* FROM "events" INNER JOIN "attendances" ON "attendances"."event_id" = "events"."id" WHERE "attendances"."user_id" = 59 AND "attendances"."attend_status" = 0@H_502_4@这就是我想要的
但这似乎是可怕的语法,令人困惑. @H_502_4@2)使用包括 @H_502_4@如果我使用include而不是join,我不会得到重复加入.由于它分开加载事件,并且足够聪明,无法重复.
Event scope :is_attending,-> { includes(:attendances).where(attendances: {attend_status: Attendance.attend_statuses[:attending] })}@H_502_4@但是我不想加载. @H_502_4@3)ASSUME表已经加入到范围之外 @H_502_4@最后我可以假设表已经加入了调用范围之外,
Event scope :is_attending,-> { where(attendances: {attend_status: Attendance.attend_statuses[:attending] })}@H_502_4@但这似乎对我来说有点愚蠢的设计,使得这个命名范围不太可用. @H_502_4@所以我的问题 @H_502_4@1)最好的方法是什么?
最合乎逻辑的
user.events.is_attending是我最理想的用途. @H_502_4@2)有没有办法告诉活动记录忽略连接,如果他们已经发生了?
解决方法
我会使用接近你的第一个建议的东西,除了我将范围直接合并到你的内部模型(Attendance)上.
@H_502_4@所以而不是:
@H_502_4@Event.for_user(用户).merge(Event.is_attending)
@H_502_4@我会去:
@H_502_4@Event.for_user(用户).merge(Attendance.is_attending)
@H_502_4@这是一个清晰的语法.您的is_attending范围不需要连接,每个类都负责了解如何过滤自身.
@H_502_4@如果经常使用它,您可以创建一个for_attending_user(用户)范围来隐藏合并:
class Event scope :for_attending_user,-> user { for_user(user).merge(Attendance.is_attending) } ...