title: why is this rails association loading individually after an eager load?
body: <p>I'm trying to avoid the N+1 queries problem with eager loading, but it's not working. The associated models are still being loaded individually.</p>
  
  <p>Here are the relevant ActiveRecords and their relationships:</p>
  
  <pre><code>class Player &lt; ActiveRecord::Base
    has_one :tableau
  end
  
  Class Tableau &lt; ActiveRecord::Base
    belongs_to :player
    has_many :tableau_cards
    has_many :deck_cards, :through =&gt; :tableau_cards
  end
  
  Class TableauCard &lt; ActiveRecord::Base
    belongs_to :tableau
    belongs_to :deck_card, :include =&gt; :card
  end
  
  class DeckCard &lt; ActiveRecord::Base
    belongs_to :card
    has_many :tableaus, :through =&gt; :tableau_cards
  end
  
  class Card &lt; ActiveRecord::Base
    has_many :deck_cards
  end
  
  class Turn &lt; ActiveRecord::Base
    belongs_to :game
  end
  </code></pre>
  
  <p>and the query I'm using is inside this method of Player:</p>
  
  <pre><code>def tableau_contains(card_id)
    self.tableau.tableau_cards = TableauCard.find :all, :include =&gt; [ {:deck_card =&gt; (:card)}], :conditions =&gt; ['tableau_cards.tableau_id = ?', self.tableau.id]
    contains = false
    for tableau_card in self.tableau.tableau_cards
      # my logic here, looking at attributes of the Card model, with        
      # tableau_card.deck_card.card;
      # individual loads of related Card models related to tableau_card are done here
    end
    return contains
  end
  </code></pre>
  
  <p>Does it have to do with scope? This tableau_contains method is down a few method calls in a larger loop, where I originally tried doing the eager loading because there are several places where these same objects are looped through and examined. Then I eventually tried the code as it is above, with the load just before the loop, and I'm still seeing the individual SELECT queries for Card inside the tableau_cards loop in the log. I can see the eager-loading query with the IN clause just before the tableau_cards loop as well.</p>
  
  <p>EDIT: additional info below with the larger, outer loop</p>
  
  <p>EDIT2 : corrected loop below with tips from answers</p>
  
  <p>EDIT3 : added more details in loop with goals</p>
  
  <p>Here's the larger loop. It is inside an observer on after_save</p>
  
  <pre><code>def after_save(pa)
    turn = Turn.find(pa.turn_id, :include =&gt; :player_actions)
    game = Game.find(turn.game_id, :include =&gt; :goals)
    game.players.all(:include =&gt; [ :player_goals, {:tableau =&gt; [:tableau_cards =&gt; [:deck_card =&gt; [:card]]]} ])
    if turn.phase_complete(pa, players)  # calls player.tableau_contains(card)
      for goal in game.goals
        if goal.checks_on_this_phase(pa)
          if goal.is_available(players, pa, turn)
            for player in game.players
              goal.check_if_player_takes(player, turn, pa)
                ... # loop through player.tableau_cards
              end
            end
          end
        end
      end
    end
  </code></pre>
  
  <p>Here's the relevant code in the turn class:</p>
  
  <pre><code>def phase_complete(phase, players)
    all_players_complete = true
    for player in players
      if(!player_completed_phase(player, phase))
        all_players_complete = false
      end
    end
    return all_players_complete
  end
  </code></pre>
  
  <p>the <code>for player in game.players</code> is doing another query to load the players. It is cached, I mean it has the CACHE label in the log, but I would've thought there would be no query at all because the game.players should already be loaded in memory.</p>
  
  <p>Another snippet from the Goal model:</p>
  
  <pre><code>class Goal &lt; ActiveRecord::Base
    has_many :game_goals
    has_many :games, :through =&gt; :game_goals
    has_many :player_goals
    has_many :players, :through =&gt; :player_goals
  
    def check_if_player_takes(player, turn, phase)
      ...
      for tab_card in player.tableau_cards
      ...
    end
  end
  </code></pre>