32

I have a relationship between 2 models in my rails application. I have veered away from the standard of how to implement the relationship as I used another field as a primary key and the naming convention is different. Doing so resulted in the relationship seemingly not being established. I want to understand as to why.

This is a trimmed down version of my models:

class Player < ActiveRecord::Base
  set_primary_key "alias"
  attr_accessible :alias, :avatar
  has_many :player_sessions, :foreign_key => "player_alias", :class_name => "PlayerSession" 
end

class PlayerSession < ActiveRecord::Base
  attr_accessible :player_alias, :total_score
  belongs_to :player, :foreign_key  => "player_alias", :class_name => "Player" 
end

The Player model has the field alias which is the username in my application. I wanted the username to act as the primary key since it is unique and it would be easier to migrate the data and maintain relationships.

Originally I only had PlayerSession model with data already filled in, but as my application grew I added the Player model and simply inserted a row with the same alias.

In the Player's show view I have the following code:

Player Sessions:
<% @player.player_sessions do |player_session| %>
<ul>
    <li><h4>Highest Score:</h4> <%= player_session.total_score %> </li>
</ul>

When I try to access the page it simple doesn't show the information.

Other information I can add is that I haven't added any relationships in the database itself.

I am still new to rails and still playing around with it. Any opinions that concern coding standards(outside from answering the question) are welcome.


Update I have implemented Babur Usenakunov's suggestion by adding the primary_key option in the models:

class Player < ActiveRecord::Base
  set_primary_key "alias"
  attr_accessible :alias, :avatar
  has_many :player_sessions, :primary_key => "alias", :foreign_key => "player_alias", :class_name => "PlayerSession" 
end

class PlayerSession < ActiveRecord::Base
  attr_accessible :player_alias, :total_score
  belongs_to :player, :primary_key => "alias", :foreign_key  => "player_alias", :class_name => "Player" 
end

Also to test out the the data is valid I acquired the PlayerSession list manually:

Code implemented in controller:

@player_sessions =  PlayerSession.where("player_alias = ?", params[:id])

Code implemented in view(which outputs the data):

<% @player_sessions.each do |player_session| %>
<ul>
    <li><h4>Highest Score:</h4> <%= player_session.total_score %> </li>
</ul>
<% end %>
Drahcir
  • 12,311
  • 19
  • 63
  • 76
  • 1
    I'm not sure but maybe you should pass primary key in options as well. E.g. `has_many :player_sessions, :primary_key => 'alias', :foreign_key => 'player_alias' :class_name => 'PlayerSession'` and `belongs_to :player, :primary_key => 'alias', :foreign_key => "player_alias", :class_name => "Player"` – Babur Ussenakunov Jun 01 '13 at 20:27
  • Tried it that way but still doesn't work – Drahcir Jun 02 '13 at 13:17
  • @Drahcir, I am inclined to think Babur Usenakunov's suggestion should have worked. What does `@player.player_sessions` return after you tried their suggestion? – Sun Jun 02 '13 at 15:14
  • @Sunxperous it turns out that it was a silly mistake that caused the issue. Please see the answer below. (I have yet to wait till to tomorrow to mark it as answered). – Drahcir Jun 02 '13 at 18:37

2 Answers2

28

I have solved the issue, it was a matter of adding each in the loop I implemented in the view:

<% @player.player_sessions.each do |player_session| %>
<ul>
    <li><h4>Highest Score:</h4> <%= player_session.total_score %> </li>
</ul>    
<% end %>

After playing around a bit, I realised i didn't need to add the primary_key option in either of the views, and left the foreign key option only in the Player model.

class Player < ActiveRecord::Base
  set_primary_key "alias"
  attr_accessible :alias, :avatar
  has_many :player_sessions, :foreign_key => "player_alias", :class_name => "PlayerSession" 
end

class PlayerSession < ActiveRecord::Base
  attr_accessible :player_alias, :total_score
  belongs_to :player, :class_name => "Player" 
end
Drahcir
  • 12,311
  • 19
  • 63
  • 76
  • Can you help me with this one ?? http://stackoverflow.com/questions/25047920/rails-belongs-to-with-custom-column-name – mariowise Jul 30 '14 at 22:25
3

If your PlayerSession table has a column named alias then your foreign key should also be alias, not player_alias. As a token of advice I'd be wary of using an alias as a foreign_key: if your player can/decide to change his alias then all PlayerSession records within your database will become invalid and require an update. Using an immutable parameter such as player_id would be preferable to using the existing alias column IMHO.

marcelowiermann
  • 265
  • 2
  • 5
  • The alias is the player's username. So it cannot be changed. It's like deciding to change your email address and keeping all your emails – Drahcir Jun 02 '13 at 07:52