如何在Ruby on Rails中优化此代码?

时间:2014-12-20 11:58:59

标签: ruby-on-rails mongoid

我有3个模型 source.rb 属于 category.rb feed_entry.rb 属于source.rb。

我需要在类别

中显示feed_entries
  

类别名称

     

FeedEntry 1

     

FeedEntry 2

     

FeedEntry 3

现在看起来像这样

class CategoriesController < ApplicationController
  def show
    @category = Category.find(params[:id])
    @sources = @category.sources.all
  end
end

show.html.erb

<%= @category.name %></h4>

<% @sources.each do |source| %>
  <% source.feed_entries.each do |feed_entry| %>
    <%= link_to feed_entry.name, feed_entry %>
    <%= feed_entry.source.title %>
  <% end %>
<% end %>

这很慢

我使用mongoid 4,rails 4

模型

class Category
  include Mongoid::Document
  field :name, type: String
  has_many :sources, dependent: :destroy
end

class FeedEntry
  include Mongoid::Document
  field :name, type: String
  belongs_to :source, touch: true
  validates :source_id, presence: true
end

class Source
  include Mongoid::Document
  field :title, type: String
  has_many :feed_entries, dependent: :destroy
  belongs_to :category, touch: true
end

3 个答案:

答案 0 :(得分:3)

有些人想知道:

  • 除非您知道结果数据的大小,否则永远不要使用.all。始终使用分页或限制。

  • 当您在视图中看到each之类的循环时,会调用这样的查询:

    • 给我一个类别
    • 给我来源
    • 为我提供源1的供稿条目
    • 为我提供源2的供稿条目
    • ....

您应该像以下一样加载您的关联:

@sources = @category.sources.limit(20).includes(:feed_entries)

这将是这些查询:

  • 给我一个类别
  • 给我来源
  • 为我提供这些来源的供稿条目

如果您不想要任何有关类别的信息(比如我认为),您应该为模型添加关系:

Class Category
  has_many :sources
  has_many :feed_entries, :through => :sources
end

然后在您的控制器中调用

@feed_entries = @category.feed_entries

这只会进行一次查询:

  • 给我分类
  • 为我提供该类别的Feed条目

那就是它!

答案 1 :(得分:0)

我找到了解决方案:

在Category.rb中添加feed_entries

class Category
  def feed_entries
    FeedEntry.in(source_id: sources.map(&:id))
  end
end

和show.html.erb

<% @category.feed_entries.includes(:source).each do |feed_entry| %>
  <%= link_to feed_entry.name, feed_entry %>
  <%= feed_entry.source.title %>
<% end %>

答案 2 :(得分:-1)

使用has_and_belongs_to_many关系

然后控制器中的@feed_entries = @category.feed_entries应该在没有n + 1查询的情况下工作