Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eager loading a custom join with an instance variable

Given a system that allows users to invite other users to events:

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

I'm generating a simple report that shows all the invites for an event. I'm trying to modify the report to also include some actions that can be done against the invited for the sample event:

<%- 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 -%>

This works fine but has a N+1 issue. Attempting to eager load the custom association gives:

DEPRECATION WARNING: The association scope 'invited' is instance dependent (the scope block takes an argument). Preloading happens before the individual instances are created. This means that there is no instance being passed to the association scope. This will most likely result in broken or incorrect behavior. Joining, Preloading and eager loading of these associations is deprecated and will be removed in the future.

Is there a way to do eager loading like this? Is it possible to give other hints to the has_many instead of using a instance variable?

like image 354
Kevin Sylvestre Avatar asked Mar 02 '26 06:03

Kevin Sylvestre


1 Answers

See Rails 5 how to form association between tables on multiple shared attributes.

You may need to define two different associations. One instance-specific and the other to use during joins.

like image 166
s2t2 Avatar answered Mar 03 '26 22:03

s2t2