0

目前有一个非常低效的视图部分,它按预测分数列出用户组。

组控制器

def show

  @sfs_ordered = ScoreFootballSimple.order("home_score DESC, away_score ASC")
  @live_games = Game.find(:all, :conditions => ['kickoff <  ?  AND completed != true AND game_state is NOT NULL', Time.now])

group#show(相关部分)

<% @live_games.each do |game| %>
  <% @sfs_ordered.each do |sfs| %>
    <% got_this_score = Array.new %>
    <% game_points = nil %>
    <% @group.members.each do |member| %>
      <% if pred = member.prediction_set.predictions.where('game_id = ?',game.id).first %>
        <% game_points = pred.points if !pred.points.nil? && pred.score_type == sfs.score_type %>
        <% got_this_score << member.user.user_detail.display_name if pred.score_type == sfs.score_type %>
      <% end %>
    <% end %>
    <% if got_this_score.count > 0 %>
      <tr><td><%= sfs.home_score %>-<%=sfs.away_score%></td>
      <td><% if !game_points.nil? %>
            <div class="preds-show-points-div"><%= game_points %>pts</div>
          <% else %>
             -
          <% end%></td>
       <td><%= got_this_score.to_sentence %></td></tr>
     <% end%>
  <% end %>
<% end %>

显然,这是循环中的循环,这意味着对于每个@sfs_ordered(大约 50 条记录),它正在迭代每个组成员(对于大约 5000 个最大的组),这意味着页面需要几秒钟才能加载。

不要激怒我,这是展示它的外观的 POC,但它暴露了我在 ActiveRecord 方面的能力不足。现在我可以创建用户、预测集等的哈希值,但我想知道是否有人可以指出我使用 Rails 查询更精确地选择信息的更好方法。

实体关系是这样的

  • 有很多成员
  • 成员属于UserPredictionSet
  • PredictionSet有很多Prediction
  • Prediction属于GameScoreType
  • ScoreTypeSimple有一个ScoreType

预测分数在ScoreTypeSimple中- 这就是我希望列表组织的方式

例如 1:1 - Joe、Fred 和 Jane 1:0 - Sue、Dave 和 Helen

然后我想为Group .member.prediction_set.prediction 获取Group .member.user.name - 其中 prediction.game.id == game.id AND score_type == sfs.score_type

我知道我可以通过纯 SQL 连接和 IN 以及构建散列来改进这一点,但我想知道是否有人可以给我任何指示,如果有一种 Rails/Ruby 有效的方法来做到这一点。我知道答案可能在 lambda 中,但我的 ActiveRecord 知识在这里已经达到了极限!

感激地收到任何帮助。

彼得

4

1 回答 1

0

您可能会从预先加载中受益,因为您正在显示所有一些关联的对象。这是使用.includes关系上的方法完成的。例如,您的视图适用于组的所有成员,因此当您从数据库中获取组时(我没有在您的代码中看到执行此操作的行,但它可能看起来像

@group = Group.where('some condition').first

如果你改用这个:

@group = Group.includes(:members => [:user]).where('some condition').first

然后加载组、所有成员及其所有用户对象是 3 个数据库查询,而不是(在 5000 个成员的极端情况下)10,001 个。

我会说这充其量只是您解决方案的一小部分,但它可能会有所帮助。

编辑:这是 RailsCast 急切加载,并且有一些文档大约在这个页面的一半。

于 2012-06-11T14:30:48.007 回答