Подтвердить что ты не робот

Rails имеет дочерние строки count

Что такое "путь рельсов", чтобы эффективно захватывать все строки родительской таблицы вместе с количеством числа детей, которое имеет каждая строка?

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

Пример блога клише: Таблица статей. В каждой статье есть 0 или более комментариев.

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

Однако в идеале я не хочу перебирать список и создавать отдельные вызовы sql для каждой статьи, а также не хочу использовать :include для предварительной выборки всех данных и обработки их на сервере приложений.

Я хочу запустить один оператор SQL и получить один результирующий набор со всей информацией.

Я знаю, что могу полностью закодировать полный SQL и, возможно, использовать .find и просто установить параметры :joins, :group и :conditions... НО Мне интересно, есть ли "лучший" способ... иначе "путь рельсов"

Заранее спасибо

4b9b3361

Ответ 1

Этот вызов activerecord должен делать то, что вы хотите:

Article.find(:all, :select => 'articles.*, count(posts.id) as post_count',
             :joins => 'left outer join posts on posts.article_id = articles.id',
             :group => 'articles.id'
            )

Это вернет список объектов статьи, каждый из которых имеет на нем метод post_count, который содержит количество сообщений в статье в виде строки.

Метод выполняет sql, подобный следующему:

SELECT articles.*, count(posts.id) AS post_count
FROM `articles`
LEFT OUTER JOIN posts ON posts.article_id = articles.id
GROUP BY articles.id

Если вам интересно, это пример результатов MySQL, которые вы можете увидеть при запуске такого запроса:

+----+----------------+------------+
| id | text           | post_count |
+----+----------------+------------+
|  1 | TEXT TEXT TEXT |          1 |
|  2 | TEXT TEXT TEXT |          3 |
|  3 | TEXT TEXT TEXT |          0 |
+----+----------------+------------+

Ответ 2

Версия Rails 3

Для Rails 3 вы будете выглядеть примерно так:

Article.select( "articles.*, count(comments.id) AS comments_count" )
  .joins( "LEFT OUTER JOIN comments ON comments.article_id = articles.id" )
  .group( "articles.id" )

Благодаря Gdeglin для версии Rails 2.

Ответ 3

Простым способом, который я использовал для решения этой проблемы, был

В моей модели я сделал:

class Article < ActiveRecord::Base
  has_many :posts

  def count_posts
    Post.where(:article_id => self.id).count
  end
end

Теперь вы можете использовать, например:

Articles.first.count_posts

Я не уверен, что это может быть более эффективным способом, Но его решение и, на мой взгляд, более элегантно, чем другие.

Ответ 4

С точки зрения SQL это выглядит тривиально. Просто напишите новый запрос.

С точки зрения Rails значения, которые вы указываете, являются вычисленными значениями. Поэтому, если вы используете find_by_sql, класс Model не будет знать о вычисленных полях и, следовательно, вернет вычисленные значения в виде строк, даже если вам удастся перевести запрос в Rails. См. Связанный вопрос ниже. Общий дрейф (из ответов, которые я получил на этот вопрос) заключался в том, чтобы отдельный класс отвечал за свертывание/вычисление желаемых значений.

Как получить рельсы для возврата атрибутов SUM (columnName) с правильным типом данных вместо строки?