Forum: Ruby on Rails 'each' loop 2 times trough all records

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
018b3c8f428a528431a2ccd65b4d37e4?d=identicon&s=25 Thierry Delbart (thithi32)
on 2008-10-24 23:23
Hello,

I'm having some troubles today with Ruby...

I do
    @league = League.find(params[:id], :include => [ :teams, :games ])

then
    @league.teams.each do |t|

and it goes 2 times through the teams list ??? even if
@league.teams.size = 2.

Does anyone have a clue where it can come from??

Thank you for you help,

Thierry
D6434aa0b7b350f8c3ed0119d81b2ead?d=identicon&s=25 Roy Pardee (rpardee)
on 2008-10-25 00:23
(Received via mailing list)
Could the inclusion of the games records be multiplying the number of
teams that get returned maybe?  Any difference if you take :games out of
that :include array there?
018b3c8f428a528431a2ccd65b4d37e4?d=identicon&s=25 Thierry Delbart (thithi32)
on 2008-10-25 00:37
Sure there should be something about it because there's 2 teams per
games.
But Teams belongs to League and Games belongs to 2 Teams. But since
there a direct link between Team and League I didn't expect the Games to
affect the Team list (I would have expected it the other way around with
2 times each games).

See below my models:

class League < ActiveRecord::Base
    has_many :teams
    has_many :games, :through => :teams
end

class Team < ActiveRecord::Base
    belongs_to :club
    belongs_to :league
    has_many :games, :foreign_key => 'team_a_id'
    has_many :games, :foreign_key => 'team_b_id'
end

class Game < ActiveRecord::Base
    belongs_to :team_a, :class_name => 'Team', :foreign_key=>'team_a_id'
    belongs_to :team_b, :class_name => 'Team', :foreign_key=>'team_b_id'
end
D6434aa0b7b350f8c3ed0119d81b2ead?d=identicon&s=25 Roy Pardee (rpardee)
on 2008-10-25 01:15
(Received via mailing list)
Huh--interesting, those two has_many :games calls in your Team class
there.  Does that result in a single @my_team.games collection property
that gives the complete list of games, whether they were team_a or
team_b?  My intuition is that the second call would sort of overwrite
the first & you wouldn't see the games from the team_a_id link.

I tried to test this design out (I'm using rails 2.0.2) and that seems
to be what happens.  Only one of the two teams I added to a game had
anything in its .games collection.

I'd be tempted to do something like this instead:

class Team < ActiveRecord::Base
    belongs_to :club
    belongs_to :league
    has_many :a_games, :class_name => 'game', :foreign_key =>
'team_a_id'
    has_many :b_games, :class_name => 'game', :foreign_key =>
'team_b_id'

  def games
    # mash the two games collections together manually.
    a_games + b_games
  end

end

Not that any of this addresses your problem, necessarily...

-Roy
018b3c8f428a528431a2ccd65b4d37e4?d=identicon&s=25 Thierry Delbart (thithi32)
on 2008-10-25 03:35
Wow! Thank you for the help.

I came to the same conclusions as you that just the B team games
counted...

I didn't know I do this "def games" definition ... I was looking for
that 3 months ago! Thank you.

I used the .uniq function to clean multiple occurence of teams and
games.

There probably is a better way to write the code below:
    @games = []
    listForTeams = @league.teams.uniq.dup
    listForTeams.each do |t|
        @games.concat(t.games)
    end
    @games.uniq!

I I has to change part of my code to deal with team.games as a function
and not an association.
For example, a replaced:

h[:gameplayed] = @games.find(:all, :conditions => ["team_a_id = (?) OR
team_b_id = (?)", t.id, t.id]).size()

by

gamesplayed = @games.select { |v| v.team_a_id == t.id || v.team_b_id ==
t.id }
h[:gamesplayed] = gamesplayed.size()

it works fine, I hope I'll have no problem going to an Ajax table with
those data.

Thanks again for your time.

Thierry
This topic is locked and can not be replied to.