【问题标题】:Ruby on Rails Nested LoopRuby on Rails 嵌套循环
【发布时间】:2014-04-12 21:03:57
【问题描述】:

我对 Rails 还很陌生,我正在尝试找出最好的方法。

我有一张球员桌和一张球队桌。它们彼此都是 HABTM,并使用连接表。

型号

class Player < ActiveRecord::Base
  has_and_belongs_to_many :teams
end

class Team < ActiveRecord::Base
  has_and_belongs_to_many :players
end

控制器

def players
  @players = Player.all
end

查看

<%@players.each do |player|%>
    <tr>
      <td><%= link_to "Add", "steam://friends/add/#{player.steamid}"%></td>
      <td><%= link_to player.name, player%></td>
      <td><%=player.email%></td>
      <td><%=player.teams.teamname%></td>
    </tr>
<%end%>

首先,我知道 teamname 应该是 team_name。

我尝试构建一个循环遍历团队的循环,但此页面有超过 1600 名玩家,因此运行它需要几分钟时间。

我是否错过了更好的方法来做到这一点?

【问题讨论】:

    标签: ruby-on-rails-3 rails-activerecord erb


    【解决方案1】:

    这很慢的原因是因为您正在为每个用户执行另一个查询。这就是所谓的 N+1 问题,因为这就是算法复杂度。

    通过更有效地从数据库中检索数据来解决这个问题很容易。您可以使用Eager Loading 告诉 Rails 加载所有必要的记录。

    在这种情况下,就这么简单:

    @players = Player.includes(:teams).all
    

    Rails 将执行一个查询以检索所有玩家,然后执行第二个查询以检索所有团队,您将可以以同样的方式访问它们——您的视图根本不需要更改!

    【讨论】:

    • 嘭!我知道有一种方法可以加快速度。但这意味着最好的方法是更改​​我在上面编写视图的方式并将其作为循环放回,对吗?
    • 我添加了这个&lt;%player.teams.each do |team| puts team.teamname end%&gt;,它的加载速度非常快,太棒了。但我不认为我使用 puts 的语法是正确的,因为它没有写任何东西。
    • &lt;%=player.teams.map{|team| team.teamname}%&gt; 我需要这样的东西,是吗?尽管我认为我需要将其包装在 raw 中,但这似乎显示得更好。
    • 如果您想显示多个团队,是的,您需要遍历它们以进行显示。你也可以很容易地做到这一点:player.teams.map(&amp;:teamname).to_sentence。您不想在 ERb 视图中使用 puts — 您想使用 &lt;%= 开头“标签”来表示应该呈现响应。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 2018-12-28
    • 2011-06-02
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多