Reputation: 35
I'm a noob trying to build up my first rails app. It's a "betting game" where users try to predict football results and get points for correct result or correct "tendency" (win, draw, loose).
Creating and updating bets is working fine, also creating games and inserting results as an admin user. But I'm having problems in displaying all bets from all users for each game in a kind of an index page, which should roughly look like this:
| User1 | User2 | User3 ...
Game Result | Bet | Bet | Bet
Team1 : Team2 1:0 | 1:1 | 3:2 | 1:0
Team3 : Team4 1:2 | 1:2 | -:- | 3:0
Team5 : Team6 -:- | 1:2 | -:- | 3:0
...
My Model structure looks like this:
class User < ActiveRecord::Base
has_many :bets
class Game < ActiveRecord::Base
has_many :bets
class Bet < ActiveRecord::Base
belongs_to :user, :class_name => 'User', :foreign_key => 'user_id'
belongs_to :game, :class_name => 'Game', :foreign_key => 'game_id'
Indicated by the -:- in the above scetch, not every user will have placed a bet on every game, and not every game will have a result.
I tried a thousand ways of getting the data together for the index view and got issues with multiple errors (nil object, no method etc.). The current (not working) approach is getting everything in the controller:
def index
@users = User.all
@games = Game.all
@bets = Bet.all
end
and in the view trying to iterate to the games and within each games through the users and bets in the view, while checking if a bet of a user and a game exists, which leads to unreadable messy code there:
<% @games.each do |game| %>
<tr>
<td><%= game.home_team %> - <%= game.away_team %></td>
<td>
<% if game.away_score.nil? %>
-:-
<% else %>
<%= game.home_score %> : <%= game.away_score %>
<% end -%>
</td>
<% @users.each do |user| %>
<% bet = Bet.where( :user_id => user.id, :game_id => game.id) %>
<% if bet.exists? %>
<td><%= bet.home_bet %> : <%= bet.away_bet %></td>
<% else %>
<td>-:-</td>
<% end -%>
<% end -%>
</tr>
<% end -%>
I hope you can suggest a cleaner way to accomplish this. Unfortunately, none of the dozens of posts I read could solve my problem.
So, the first question is: what is the best way to retrieve the needed data from the different tables? Corresponding second Question: Is it best to build the data in the controller and pass it to the view or put it all together in the view?
I'm using rails 3.1.1 with squlite3. I hope, someone can help this stupid newbee...
Upvotes: 0
Views: 1065
Reputation: 9225
I would probably do something like this:
controller:
@users = User.all
@game_bets = Game.all.map { |game| [game, game.bets.index_by(&:user)] }
view:
<% @game_bets.each do |game, bets| %>
...
<% @users.each do |user| %>
<% if bets.has_key?(user) %>
<td><%= bets[user].home_bet %></td>
<% else %>
<td>-:-</td>
...
Upvotes: 0
Reputation: 29135
So many issues here... let's start
there's no need to iterate through ALL users for EACH game. You can iterate through game.bets
and for each 'bet' get a user by bet.user
, according to the relationship you have built
To answer your 1st question: since you are trying to make a 'report' kind of a view with an intent to show 'all' games, your approach to have @games = Game.all
is right. You don't need 2 other .all
collections though since you can infer the data from the relationships
2nd question: In Rails it is considered a good approach to have 'fat models, skinny controllers' which means that your data crunching/logic code should be in a model and controller should have only code used by the correspondent views.
About your view: In your case your view is not terribly bad since you have a sparsely populated tables and you should use if
s for cases where score is not available etc
Upvotes: 1