Rails: сбор данных из трех связанных моделей в одном представлении - PullRequest
0 голосов
/ 08 февраля 2012

Я нуб, пытаюсь создать свое первое приложение для rails.Это «игра в ставки», в которой пользователи пытаются предсказать результаты футбола и получить очки за правильный результат или правильную «тенденцию» (выиграть, сыграть в ничью, проиграть).

Создание и обновление ставок работает нормально, также создаются игры ивставка результатов в качестве администратора.Но у меня возникают проблемы с отображением всех ставок от всех пользователей для каждой игры в виде страницы индекса, которая должна выглядеть примерно так:

                       |  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 
...

Структура моей модели выглядит следующим образом:

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'

Обозначается -: - в приведенном выше наброске, не каждый пользователь сделает ставку на каждую игру, и не каждая игра будет иметь результат.

Я попробовал тысячи способов собрать данные для представления индекса и получил проблемы с множественными ошибками (объект nil, метод и т. Д.).Текущий (не работающий) подход заключается в получении всего в контроллере:

def index
    @users = User.all
    @games = Game.all
    @bets = Bet.all
end

и в представлении, пытаясь перейти к играм и внутри каждой игры через пользователей и ставки в представлении, проверяя, еслиставка на пользователя и игра существует, что приводит к нечитаемому грязному коду:

    <% @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 -%>

Я надеюсь, что вы можете предложить более чистый способ сделать это.К сожалению, ни одна из десятков постов, которые я прочитал, не может решить мою проблему.

Итак, первый вопрос: каков наилучший способ получения необходимых данных из разных таблиц?Соответствующий второй вопрос: лучше ли собирать данные в контроллере и передавать их в представление или объединять все вместе в представлении?

Я использую rails 3.1.1 с squlite3.Надеюсь, кто-то может помочь этому глупому новичку ...

Ответы [ 2 ]

1 голос
/ 08 февраля 2012

Здесь так много вопросов ... давайте начнем

  1. нет необходимости перебирать ВСЕХ пользователей для КАЖДОЙ игры. Вы можете выполнить итерацию по game.bets и за каждую 'ставку' получить пользователя на bet.user, в соответствии с вашими отношениями

  2. Чтобы ответить на ваш 1-й вопрос: поскольку вы пытаетесь сделать вид «отчета» с намерением показать «все» игры, ваш подход к @games = Game.all правильный. Вам не нужны еще 2 .all коллекции, так как вы можете вывести данные из отношений

  3. 2-й вопрос: В Rails считается хорошим подходом иметь «толстые модели, тощие контроллеры», что означает, что ваш код обработки данных / логический код должен быть в модели, а контроллер должен иметь только код, используемый корреспондентом. Просмотры.

  4. О вашем представлении: в вашем случае ваше представление не очень плохое, поскольку у вас есть малонаселенные таблицы, и вы должны использовать if s для случаев, когда оценка недоступна и т. Д.

0 голосов
/ 08 февраля 2012

Я бы, наверное, сделал что-то вроде этого:

контроллер:

@users = User.all
@game_bets = Game.all.map { |game| [game, game.bets.index_by(&:user)] }

просмотр:

<% @game_bets.each do |game, bets| %>
  ...
  <% @users.each do |user| %>
    <% if bets.has_key?(user) %>
      <td><%= bets[user].home_bet %></td>
    <% else %>
      <td>-:-</td>
...
...