Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 活动记录范围链接,忽略连接(如果已连接)_Ruby On Rails_Activerecord - Fatal编程技术网

Ruby on rails 活动记录范围链接,忽略连接(如果已连接)

Ruby on rails 活动记录范围链接,忽略连接(如果已连接),ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我已建模,用户已参加活动 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 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}
我的问题是关于范围查询和最佳实践

我已将大部分范围查询放在事件上

我想获取特定用户的所有事件,其中Attention_status=0

user = User.find(...)
user.events.is_attending
从逻辑上讲,我认为,这读起来最好,也最有意义

然而,这将给我一个双重的内部连接

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
很明显,这会产生重复,这不是我想要的

所以我知道我能做的选择

1) 使用合并

Event
  scope :for_user, -> (user){ joins(:attendances).where(attendances: {user: user})}
然后打电话

Event.for_user(user).merge(Event.is_attending)
这给了我sql

SELECT "events".* FROM "events" INNER JOIN "attendances" ON "attendances"."event_id" = "events"."id" WHERE "attendances"."user_id" = 59 AND "attendances"."attend_status" = 0
这就是我想要的。 但这似乎是糟糕的语法,令人困惑

2) 用途包括

如果使用includes而不是join,则不会得到重复的join。因为它单独加载事件,并且足够智能,不会重复

Event
  scope :is_attending, -> { includes(:attendances).where(attendances: {attend_status: Attendance.attend_statuses[:attending] })}
但是我不想急于加载

3) 假设表已在范围外联接

最后,我可以假设表已经在调用范围之外连接

Event
  scope :is_attending, -> { where(attendances: {attend_status: Attendance.attend_statuses[:attending] })}
但在我看来,这似乎有点愚蠢,并使这个命名范围不太可重用

所以我的问题是

1) 最好的方法是什么? 最合乎逻辑的
user.events.is\u atticing
是我理想的选择


2) 有没有办法告诉Active Record忽略已经发生的连接?

我会使用与您的第一个建议相近的内容,但我会直接在您的内部模型(考勤)上合并一个范围

因此,不是:

事件。对于用户(用户)。合并(事件。是否参与)

我会选择:

事件。对于用户(用户)。合并(出席。是否出席)

这是一个清晰的语法。您的is_参与范围不需要有联接,每个类负责知道如何过滤自身

如果您经常使用它,您可以为用户(用户)范围创建一个
来隐藏合并:

class Event
  scope :for_attending_user, -> user { for_user(user).merge(Attendance.is_attending) }
  ...

您可以向
用户
模型中添加与
正在参与
条件的关联:

class Attendance < ActiveRecord::Base
  belongs_to :event
  belongs_to :user
  enum attend_status: { attending: 0, not_attending: 1}

  scope :is_attending, -> { where(attend_status: attend_statuses[:attending]) }
end

class User < ActiveRecord::Base
  has_many :attendances
  has_many :events, through: :attendances

  has_many :attending_events, -> { Attendance.is_attending }, through: :attendances, source: :event
end
这种方法有一个缺点:不能组合条件。但是,如果您使用的是状态列,这是有意义的。因为这种方法反映了关系的逻辑

u.attending_events

SELECT "events".* FROM "events" 
INNER JOIN "attendances" ON "events"."id" = "attendances"."event_id" 
WHERE "attendances"."user_id" = 1 AND "attendances"."attend_status" = 0  [["user_id", 1], ["attend_status", 0]]