渴望使用实例变量加载自定义联接
Posted
技术标签:
【中文标题】渴望使用实例变量加载自定义联接【英文标题】:Eager loading a custom join with an instance variable 【发布时间】:2015-08-16 18:42:00 【问题描述】:给定一个允许用户邀请其他用户参加活动的系统:
class Event
has_many :invites
end
class User
has_many :invites
has_many :invited, inverse_of: :inviter, foreign_key: :inviter_id, class_name: 'Invite'
end
class Invite
belongs_to :user
belongs_to :event
belongs_to :inviter, class_name: 'User'
has_many :invited, -> (invite) where(invites: event_id: invite.event_id ) , through: :user, class_name: 'Invite'
end
我正在生成一个简单的报告,其中显示了某个活动的所有邀请。我正在尝试修改报告以包含一些可以针对示例事件的invited
执行的操作:
<%- event.includes(:user).each do |invite| -%>
<%= invite.user.name %>
<%- invite.invited.each do |other| -%>
<%= link_to invite_path(other), method: :destroy do %>
...
<% end %>
<%- end -%>
<%- end -%>
这工作正常,但有一个 N+1 问题。尝试预先加载自定义关联会给出:
弃用警告:关联范围“已邀请”取决于实例(范围块接受参数)。预加载发生在创建单个实例之前。这意味着没有实例被传递到关联范围。这很可能会导致损坏或不正确的行为。这些关联的加入、预加载和预加载已被弃用,将来将被删除。
有没有办法像这样进行急切加载?是否可以给has_many
提供其他提示而不是使用实例变量?
【问题讨论】:
我正在尝试了解您要获取的内容。来自同一用户的邀请参加同一活动? @D-Side 是的,试图获得每个受邀用户的其他邀请。实际的例子要复杂得多,但我尽量简化了这个问题。 嗯,您正在获取每个邀请的邀请集合。这将是一个痛苦,因为它需要一个自连接,而这又需要对所涉及的表实例之一进行别名。所以,Arel 的使用似乎是必须的。 您是否需要按... 嗯... 邀请对邀请进行分组?我的意思是,一个奇怪的排序列表是否足以满足您的需求,还是您需要按相关邀请整齐地分组? 【参考方案1】:见Rails 5 how to form association between tables on multiple shared attributes。
您可能需要定义两个不同的关联。一个特定于实例,另一个在连接期间使用。
【讨论】:
【参考方案2】:尝试从事件端使用关系。喜欢:
class Invite
belongs_to :user
belongs_to :event
belongs_to :inviter, class_name: 'User'
def invited
event.invites.includes(...)
end
end
【讨论】:
基于 OPInvite.invited
查询其他 invites
与邀请具有相同的 inviter
(user) 和 event
,所以我认为您的查询 event.invites
不够。你能解释更多细节吗?以上是关于渴望使用实例变量加载自定义联接的主要内容,如果未能解决你的问题,请参考以下文章