@aykc
сплю, ем, работаю

Как извлечь количество записей и последнюю запись в has_many through ассоциации?

Имеются три модели:

class Category < ActiveRecord::Base
  has_many :posts, dependent: :destroy
  has_many :comments, through: :posts, dependent: :destroy
end


class Post < ActiveRecord::Base
  has_many :comments, dependent: :destroy
  belongs_to :category
end


class Comment < ActiveRecord::Base
  belongs_to :post
  belongs_to :category
end


Мне необходимо извлечь определенную категорию (params[:id]), все посты этой категории, а также количество комментариев на каждый пост и последний комментарий к каждому посту. Как это сделать максимально эффективно (по памяти, производительности)?

На данный момент реализованно так:

def show
  @category = Category.includes(:comments, :posts).find(params[:id])
end


В шаблоне вывожу соответственно:

<h1>@category.name</h1>
<% @category.posts.each do |post| %>
  <%= post.name %>
    <%= post.comments.count %>  <!-- либо post.comments.size, работаем с массивом, не делаем лишние запросы -->
    <%= post.comments.last.body %>
<% end %>


Понимаю, что все комментарии загружаются полностью, хотя нужны к каждому посту только последние и их количество. Если постов в категории много и комментариев в каждом посте, то соответственно это не есть хорошо. Если использовать joins вместо includes, то получается много запросов в БД. Перелопатил весь стэковерфлоу и рэйлскастс, но решения не нашел, либо попадалось на rails3 и задачи немного не те. Мне нужно на rails 4. Надеюсь на вашу помощь, вторые сутки не сплю.
Спасибо заранее.
  • Вопрос задан
  • 315 просмотров
Решения вопроса 1
mgyk
@mgyk
Если не хотите вытаскивать все, то сделайте просто отдельныe запросы на кол-во комментариев и последний и уберите из comments из includes.
@comment_cnt = Comment.where(post_id: @category.post_ids)).group(:post_id).count
@comment_last = Comment.where(post_id: @category.post_ids).group(:post_id).having('id = MAX(id)')


Потом просто @comments_last[post_id] и @comment_cnt[post_id]
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Renius
дурак восторженный
Вы что-то не договариваете

parent.children.last загрузит только 1 объект за 1 запрос к родителю и 1 запрос к ребенку
parent.children.count совершит 1 запрос к родителю и 1 запрос count к ребенку

всех детей( комменты в вашем случае) загружаться не будут

или, есть подозрение, поскольку я не вижу ваши проблемные запросы, а могу только догадываться:
попробуйте инклюдить/джойнить коменты к постам, а не к категориям
@category.posts.includes(:comments).each do |post|
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы