2014-12-20 5 views
0

У меня есть 3 модели source.rb принадлежит category.rb и feed_entry.rb принадлежит source.rb.Как оптимизировать этот код в Ruby on Rails?

мне нужно отобразить 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, рельсы 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 
+0

Обычный способ оптимизации запросов MongoDB состоит в том, чтобы перестроить вашу схему посредством денормализации и встраивания. Итак, как выглядят ваши модели? –

ответ

0

Я нашел решение:

В Category.rb добавить feed_entries

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

и in show.html.erb

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

Некоторые думают:

  • Никогда не используйте .all, если только вы не знаете размер данных результата. Всегда используйте разбивку на страницы или ограничение.

  • Когда у вас есть цикл, как ваш each ввиду, это будет вызывать запросы как это:

    • Дайте мне категорию
    • Дай мне свои источники
    • Дайте мне кормить записи для источника 1
    • Дайте мне исходные данные для источника 2
    • ....

Вы должны eagler загрузить ассоциацию, как это:

@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 

Это будет делать только ОДИН запрос:

  • Дайте мне категорию
  • Дайте мне исходные данные рубрики

Это все!

+1

Спасибо за ответ, но у mongoid нет has_many: через ассоциацию –

-1

Применение has_and_belongs_to_many Отношения

Затем @feed_entries = @category.feed_entries в контроллере должен быть работать без п + 1 запрос