Rails 3 - Запросы с подмоделями и подсчетом операторов - PullRequest
1 голос
/ 20 января 2011

Я пытаюсь найти способ устранить кучу запросов, которые кажутся ненужными. Вот ситуация.

модель Сообщение has_many Комментарии

SQL (0,1 мс) SELECT COUNT (*) ОТ "комментариев" ГДЕ ("комментарии" .post_id = 5)
CACHE (0.0ms) ВЫБЕРИТЕ COUNT (*) ОТ "comments" WHERE ("comments" .post_id = 5)
CACHE (0.0ms) ВЫБЕРИТЕ COUNT (*) ОТ "comments" WHERE ("comments" .post_id = 5)
CACHE (0.0ms) ВЫБЕРИТЕ СЧЕТЧИК (*) ОТ "комментариев" ГДЕ ("комментарии" .post_id = 5)

Так что я не уверен, почему они работают, но, на мой взгляд, я проверяю, есть ли комментарии для каждого из сообщений

<% if post.comments.count > 0 %> <!-- tried count, size, blank? -->
    <table class="list">
    <% post.comments.each do |animal| %>
        <tr><!-- stuff here --></tr>
    <% end %>
    </table>
<% else %>
    <h3>No comments</h3>
<% end %>

Если есть лучший способ сделать эту проверку, я за изменения. Я посмотрел на counter_cache, но похоже, что он предназначен только для отношений own_to, а также я использую субдомены, поэтому не уверен, что counter_cache подойдет мне или нет.

Любые предложения приветствуются

Ответы [ 2 ]

1 голос
/ 20 января 2011

Проблема здесь в том, что вы, вероятно, не с нетерпением загружаете комментарии для каждого сообщения. Где бы вы ни устанавливали переменную post в вашем контроллере, у вас, вероятно, есть что-то вроде этого:

post = Post.find(params[:id])

Попробуйте изменить это на:

post = Post.includes(:comments).find(params[:id])

Включает в себя автоматически изменит ваш запрос пост загрузки, чтобы присоединиться к комментариям и предварительно заполнить post.comments массивом всех комментариев этого поста. Затем, когда вы выполните post.comments.size, вы будете запрашивать длину массива (вместо того, чтобы просить activerecord подсчитать, сколько их существует).

0 голосов
/ 20 января 2011

Ммм ... #includes - это метод класса, вы не можете вызывать его для экземпляра, возвращенного Post.find(params[:id]) В принципе, он правильный, но синтаксис: Post.includes(:comments).find(params[:id])

В ответ на ваш комментарий:

ОК, #includes - это метод класса для ActiveRecord :: Base и его дочерних элементов (ваших моделей), но метод экземпляра для ActiveRelation.

@posts = @current_user.posts.all(:include => [:comments]).all

определенно устарел ... вы хотите сделать включение перед вызовом #all b / c в Rails 3, @current_user.posts вернет объект ActiveRelation, тогда как @ current_user.posts.all будет фактически загружать коллекцию Почтовые объекты. Поэтому я бы изменил его на:

@posts = @current_user.posts.includes(:comments).all

Если честно, вам даже не нужно даже звонить на #all, но посмотрите, какой из них лучше для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...