HABTM and Fixtures

First off, I’ve done some googling and read some very informative
stuff, but I’m having an issue and I can’t figure out what I’m doing
wrong. I’ve got it working with one model, but the other one is
choking… Here’s the relevant data (and my current stuff):

player.rb:
class Player < ActiveRecord::Base
has_and_belongs_to_many :friends,
:class_name => “Player”, :association_foreign_key =>
“friend_id”, :join_table => “friends_players”

has_and_belongs_to_many :leagues,
:class_name =>
“Player”, :association_foreign_key=>“player_id”,
:join_table=>“players_leagues”
end

league.rb:
class League < ActiveRecord::Base
has_many :players,
:class_name => “Player”, :association_foreign_key =>
“player_id”, :join_table => “players_leagues”
end


players.yml:
user1:
name: Jason
network_id: dbg_12345
friends: user2, user3

user2:
name: Shane
network_id: dbg_12346
friends: user3

user3:
name: Dan
network_id: dbg_12347
friends: user1

leagues.yml:
league1:
player_id: user1
players: user1, user2, user3

Now when I attempt to use my custom rake task to import the fixtures,
I get:

rake aborted!
Mysql::Error: #42S22Unknown column ‘players’ in ‘field list’: INSERT
INTO leagu es (players, player_id) VALUES (‘user1, user2, user3’, ‘user1’)

So, it’s not quite working, and I’m not sure why. League is actually
supposed to be owned by a player (it has a player_id) field, but I’ve
been experimenting trying to get it working.

complex setup, but let me try to sort it out a bit:

player.rb: (the friends thing has nothing to do with the problem, so i
don’t include it)

has_and_belongs_to_many :leagues

that’s default stuff, so no need to include it, makes code less
readable:
:class_name => “Player”
:association_foreign_key=>“player_id”,
:join_table=>“players_leagues”

league.rb:
has_many :players,
:class_name => “Player”, :association_foreign_key =>
“player_id”, :join_table => “players_leagues”

if i get your setup right, the wrong thing here is the has_many
it should be habtm as in players

has_and_belongs_to_many :players

again the rest of definition isn’t necessary, since you keep with naming
conventions.

leagues.yml:
league1:
player_id: user1 <= ??? why that ???
players: user1, user2, user3

is there another player_id in leagues? if so, define it as:
belongs_to :players
otherwise kick that line

i hope i understood you setup, otherwise it may be helpful to
have a few more details of the associations and the exact fieldnames in
all three used tables

Thanks Thorsten. :slight_smile:

Well the reason that league has a player_id is that is the “owner” of
the league. He’s by default a player in the league as well. Right now
that’s the last problem… I had to create leagues_players (I guess
players_leagues isn’t the convention) and modified league and player
to these:

class League < ActiveRecord::Base
has_and_belongs_to_many :players
#:class_name => “Player”, :association_foreign_key =>
“player_id”, :join_table => “players_leagues”
end

class Player < ActiveRecord::Base
has_and_belongs_to_many :friends

:class_name => “Player”, :association_foreign_key =>

“friend_id”, :join_table => “friends_players”

has_and_belongs_to_many :leagues
end

leagues.yml is currently

league1:
name: Test League
player_id: user1
playercount: 8
players: user1, user2, user3

now the rake task runs without error, and I get players being inserted
in leagues_players correctly. However the player_id is not set (the
owner of the league).

On Mar 14, 11:41 am, Thorsten M. <rails-mailing-l…@andreas-

ok, so we have the complicated part.
for the owner just define the association as well:

player.rb:

has_one :league

league.rb:
belongs_to :player

in this case i would go for renaming this like
belongs_to :owner, :foreign_key => player_id
this will make you code more readable later on
since you’ll acces your league like

@league.players
and
@league.player

which can be confusing so the combination
@league.players
@league.owner
would work better

Thanks again Thorsten, some more frustration on my end though. Adding
the “belongs_to” has broken the friends association, somehow.

class League < ActiveRecord::Base
has_and_belongs_to_many :players
#:class_name => “Player”, :association_foreign_key =>
“player_id”, :join_table => “players_leagues”

belongs_to :owner, :foreign_key => :player_id
end

class Player < ActiveRecord::Base
has_and_belongs_to_many :friends

:class_name => “Player”, :association_foreign_key =>

“friend_id”, :join_table => “friends_players”

If I comment this line out, it doesn’t complain, but the leagues

owner id (player_id) doesn’t get set

if I uncomment it, I get an error.

#has_many :leagues, :foreign_key=> player_id
end

The error I get is:
rake aborted!
Mysql::Error: #42S22Unknown column ‘friends’ in ‘field list’: INSERT
INTO players (name, network_id, friends) VALUES (‘Jason’,
‘dbg_12345’, ‘user2, user3’)

For further reference, the schema

create_table “friends_players”, :id => false, :force => true do |t|
t.integer “player_id”
t.integer “friend_id”
t.datetime “created_at”
t.datetime “updated_at”
end

add_index “friends_players”, [“friend_id”], :name =>
“index_friends_players_on_friend_id”
add_index “friends_players”, [“player_id”], :name =>
“index_friends_players_on_player_id”

create_table “leagues”, :force => true do |t|
t.string “name”
t.integer “playercount”
t.integer “player_id”
t.datetime “timestarted”
t.datetime “created_at”
t.datetime “updated_at”
end

create_table “leagues_players”, :id => false, :force => true do |t|
t.integer “league_id”
t.integer “player_id”
t.datetime “created_at”
t.datetime “updated_at”
end

add_index “leagues_players”, [“league_id”], :name =>
“index_leagues_players_on_league_id”
add_index “leagues_players”, [“player_id”], :name =>
“index_leagues_players_on_player_id”

create_table “players”, :force => true do |t|
t.string “name”
t.string “network_id”
t.datetime “created_at”
t.datetime “updated_at”
end

On Mar 14, 11:59 am, Thorsten M. <rails-mailing-l…@andreas-

On 3/14/08, Backov [email protected] wrote:

end

Based on what I understand of your requirements, this doesn’t seem quite
right.

Players don’t have many leagues, each player belongs to one league,
and may have at most one league (as it’s owner). Those are two
separate relationships, so should be modeled separately.

I think you want something like:

class League < ActiveRecord::Base
has_many :players
belongs_to :owner, :class_name => ‘Player’

this implies that the ‘leagues’ table has an owner_id field

end

class Player < ActiveRecord::Base
belongs_to :league
has_one :owned_league, :class_name => ‘League’, :foreign_key =>
:owner_id

end

leagues.yml

league1:
name: TestLeague
owner: player1a
league

league2:
name: TestLeague2
owner: player2a

players.yml
player1a:
league: league1
player1b:
league: league1
player1c:
league: league1
player2a:
league: league2
player2b:
league: league2

Of course the player names can be whatever you want, I picked player1a
etc. just to make the relelationships clear


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Ya, the difference was that players (human players, not the members of
the team) can own multiple leagues and play in mulitple leagues.

To followup my own message, I had to simplify a bit to get it working

class League < ActiveRecord::Base
has_and_belongs_to_many :players

belongs_to :player # trying to do :owner, :foreign_key here caused
an error in the parse
end

class Player < ActiveRecord::Base
has_and_belongs_to_many :friends

has_many :leagues
end

league1:
name: Test League
player: user1 < – Had to change to player instead of player_id
playercount: 8
players: user1, user2, user3

Thanks a lot for all of your help Thorsten.

On Mar 14, 11:59 am, Thorsten M. <rails-mailing-l…@andreas-