Rails父子模型查看最佳实践

时间:2015-04-24 03:18:45

标签: ruby-on-rails-4 ruby-on-rails-4.1

我有一个视图,显示父母(在我的情况下是小组)和它的孩子(在我的情况下是行)中的记录,虽然它有效,但我感觉我是没有采用正确的Rails MVC方式。

我的模特是:

class Group < ActiveRecord::Base
  has_many :lines, dependent: :destroy
  belongs_to :user
end

class Line < ActiveRecord::Base
  belongs_to :group
end

我的群组控制器打印方法是:

def print
  @groups = current_user.groups.order('position ASC').all
end

我的打印视图是:

<table class="table table-striped">
  <thead>
    <tr>
      <th>Description:</th>
    </tr>
  </thead>
  <tbody>
    <% @groups.each do |group| %>
      <tr>
        <td><h3><%= group.description %></h3></td>
      </tr>
      <% group.lines.each do |line| %>
        <tr>
          <td><%= line.description %></td>
        </tr>
      <% end %>
    <% end %>
  </tbody>
</table>

我的print方法返回所有正常的组,就像索引方法一样。它生成以下SQL:

SELECT "groups".* FROM "groups"  WHERE "groups"."user_id" = ?  ORDER BY position ASC  [["user_id", 1]]

我认为我出错的地方是我在上面的打印视图中获得了此代码:

lines group.lines.each do |line|

每次针对每个组运行时,它会生成另一个这样的查询(对于每个组:

SELECT "lines".* FROM "lines"  WHERE "lines"."group_id" = ?  [["group_id", 667]

由于查询运行很多次,这似乎效率低下。我也告诉我,我的查询实际上应该是从我的控制器运行而不是我的视图(即正确的Rails / MVC方式)。

我怎样才能做得更好?

提前致谢

1 个答案:

答案 0 :(得分:4)

您需要执行所谓的eager loading(而不是延迟加载),您需要指示rails事先查询所有子项,而不是在循环中获取每个子项,这可以轻松完成使用includes方法

def print
  @groups = current_user.groups.includes(:lines).order(position: :asc)
end

通过这种方式,您只能获得2个查询(一个用于组,一个用于行),并且在呈现视图时无查询