# Confusion about has\_many / belongs\_to

**URL:** <https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724>\
**Category:** Rails\
**Created:** [April 7, 2006, 4:55pm UTC](https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724 "2006-04-07T16:55:05Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![aginghipster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e9c0ed/32.png) [@aginghipster](https://www.ruby-forum.com/u/aginghipster)\
**Post date:** [April 7, 2006, 4:55pm UTC](https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724/1 "2006-04-07T16:55:05Z")

</div>

I have a table called players and its model Player, and I have a table  
called games and its model Game.

In the games table I have:

player1\_id int(11)  
player2\_id int(11)

I want the tables to be associated so that I can access the player  
objects using table.player1 and table.player2 rather than having to  
lookup the objects based on the ids.

I am not sure how to go about this but I suspect I need to use either  
has\_many or belongs\_to or one of the mixed versions in my Game/Player  
models.

I would be very grateful if someone could shed light on what I need to  
do here.

Thank you  
Andy

---

<div class="post-metadata">

**Author:** ![aginghipster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e9c0ed/32.png) [@aginghipster](https://www.ruby-forum.com/u/aginghipster)\
**Post date:** [April 7, 2006, 5:47pm UTC](https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724/2 "2006-04-07T17:47:05Z")

</div>

Well, if a game has more than one player, and your players can take part  
in  
more than one game (that’s an assumption, so it could be wrong;), then  
what  
you really have is a has\_and\_belongs\_to\_many relationship. That would  
give you  
a games\_players join table.

In fact, if you wanted to maintain separate player meta data, for each  
game  
they participated in, as well as game-specific meta data, you could  
actually  
structure this relationship as a has\_many :through. This would probably  
change  
the games\_players table into a participants table (or something  
similar). And  
you would put:

has\_many :games, :through =\> :participants # in the Player model  
has\_many :players, :through =\> :participants # in the Game model

and in the Participant model

belongs\_to :game  
belongs\_to :player

-Brian

---

<div class="post-metadata">

**Author:** ![aginghipster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e9c0ed/32.png) [@aginghipster](https://www.ruby-forum.com/u/aginghipster)\
**Post date:** [April 7, 2006, 6:07pm UTC](https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724/3 "2006-04-07T18:07:18Z")

</div>

A player can only participate in a single game, which should make the  
situation easy but I can’t quite figure it out…

Does the Game model has\_many :player ?

Does the Player model belongs\_to :game?

and once thats sorted out would I be able to access those associated  
objects with game.player1 and game.player2 ?

That is, does rails know that because games has player1\_id and  
player2\_id that games.player1 and games.player2 are objects from the  
players table?

You can see I am confused! 😉

-Andy

Brian V. Hughes wrote:

> Well, if a game has more than one player, and your players can take part  
> in  
> more than one game (that’s an assumption, so it could be wrong;), then  
> what  
> you really have is a has\_and\_belongs\_to\_many relationship. That would  
> give you  
> a games\_players join table.
> 
> In fact, if you wanted to maintain separate player meta data, for each  
> game  
> they participated in, as well as game-specific meta data, you could  
> actually  
> structure this relationship as a has\_many :through. This would probably  
> change  
> the games\_players table into a participants table (or something  
> similar). And  
> you would put:
> 
> has\_many :games, :through =\> :participants # in the Player model  
> has\_many :players, :through =\> :participants # in the Game model
> 
> and in the Participant model
> 
> belongs\_to :game  
> belongs\_to :player
> 
> -Brian

---

<div class="post-metadata">

**Author:** ![aginghipster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e9c0ed/32.png) [@aginghipster](https://www.ruby-forum.com/u/aginghipster)\
**Post date:** [April 7, 2006, 8:07pm UTC](https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724/4 "2006-04-07T20:07:57Z")

</div>

On Apr 7, 2006, at 9:07 AM, Andrew C. wrote:

> That is, does rails know that because games has player1\_id and  
> player2\_id that games.player1 and games.player2 are objects from the  
> players table?
> 
> You can see I am confused! 😉
> 
> -Andy

I believe what you actually need is a has\_one relationship. Although  
the game does have many players, the way the table is set up, it only  
has one player1 and one player2. Try this:

class Game \< ActiveRecord::Base  
has\_one :player1, :class\_name =\> ‘Player’  
has\_one :player2, :class\_name =\> ‘Player’  
end

You need to specify the class name because otherwise it will look for  
a class called Player1 which of course doesn’t exist. You should then  
be able to use game.player1 or game.player2 to access the players.

However, you may find this database design will cause problems later.  
If, for example, you want to support more than two players, you will  
need to add more columns for player3, player4, etc. Then what if you  
want to support, say 16 players. That is a lot of columns and could  
get messy! If this is at all a possibility, you should go with a true  
one-to-many relationship.

You would do this by putting a game\_id column in the players table  
and removing the player1 and player2 columns from the games table.  
You could then use the “has\_many :players” relationship method in  
your Game model. You can then grab the players with game.players[0]  
or game.players[1], etc. This also allows you to iterate through all  
players instead of having to refer to each one individually.

Ryan

---

<div class="post-metadata">

**Author:** ![aginghipster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e9c0ed/32.png) [@aginghipster](https://www.ruby-forum.com/u/aginghipster)\
**Post date:** [April 7, 2006, 11:29pm UTC](https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724/5 "2006-04-07T23:29:23Z")

</div>

On Apr 7, 2006, at 12:40 PM, Andrew C. wrote:

> I setup the model as suggested, identically and still have player1\_id  
> and player2\_id defined the players table, but now it seems  
> game.player1  
> and game.player2 always refer to the same object, sort of like player2  
> is an alias of player1. I suspect has\_one is causing this  
> relationship…

Sorry about that, I should have used “belongs\_to” instead of  
“has\_one” in my last e-mail. I tried this and it works:

class Game \< ActiveRecord::Base  
belongs\_to :player1, :class\_name =\> ‘Player’, :foreign\_key =\>  
‘player1\_id’  
belongs\_to :player2, :class\_name =\> ‘Player’, :foreign\_key =\>  
‘player2\_id’  
end

The problem was “has\_one” uses the game\_id column in the players  
table to do the matching. The players.game\_id column is actually  
unnecessary if you are doing it this way since it will use the  
player1\_id and player2\_id columns to do the matching.

Ryan

---

<div class="post-metadata">

**Author:** ![aginghipster](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/e9c0ed/32.png) [@aginghipster](https://www.ruby-forum.com/u/aginghipster)\
**Post date:** [April 7, 2006, 9:40pm UTC](https://www.ruby-forum.com/t/confusion-about-has-many-belongs-to/93724/6 "2006-04-07T21:40:48Z")

</div>

Ryan, I was really hoping your first suggestion would work as it sounded  
like a great way to implement this being that I have no plans to expand  
for more players down the road ( its intended for head-to-head only ).

I setup the model as suggested, identically and still have player1\_id  
and player2\_id defined the players table, but now it seems game.player1  
and game.player2 always refer to the same object, sort of like player2  
is an alias of player1. I suspect has\_one is causing this  
relationship…

However, it appears I already did setup game to have a has\_many  
relationship with the players table and indeed I can access them via  
game.players[0] and game.players[1] – I had no idea I could so this is  
a definite improvement and should prove useful.

Thank you very much, its all getting a little clearer to me now.

-Andy

Ryan B. wrote:

> On Apr 7, 2006, at 9:07 AM, Andrew C. wrote:
> 
> > That is, does rails know that because games has player1\_id and  
> > player2\_id that games.player1 and games.player2 are objects from the  
> > players table?
> > 
> > You can see I am confused! 😉
> > 
> > -Andy
> 
> I believe what you actually need is a has\_one relationship. Although  
> the game does have many players, the way the table is set up, it only  
> has one player1 and one player2. Try this:
> 
> class Game \< ActiveRecord::Base  
> has\_one :player1, :class\_name =\> ‘Player’  
> has\_one :player2, :class\_name =\> ‘Player’  
> end
> 
> You need to specify the class name because otherwise it will look for  
> a class called Player1 which of course doesn’t exist. You should then  
> be able to use game.player1 or game.player2 to access the players.
> 
> However, you may find this database design will cause problems later.  
> If, for example, you want to support more than two players, you will  
> need to add more columns for player3, player4, etc. Then what if you  
> want to support, say 16 players. That is a lot of columns and could  
> get messy! If this is at all a possibility, you should go with a true  
> one-to-many relationship.
> 
> You would do this by putting a game\_id column in the players table  
> and removing the player1 and player2 columns from the games table.  
> You could then use the “has\_many :players” relationship method in  
> your Game model. You can then grab the players with game.players[0]  
> or game.players[1], etc. This also allows you to iterate through all  
> players instead of having to refer to each one individually.
> 
> Ryan
