Ruby-on-Rails: как извлечь самые последние записи из ограниченного подмножества таблицы базы данных - PullRequest
1 голос
/ 04 марта 2010

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

Можно ли вывести последние 100 в одном запросе SQL или мне придется использовать логику приложения Ruby для разбора большего списка или выполнения нескольких запросов?

Я вижу два способа сделать это:

  1. начиная с User.find и используя некоторую сложную комбинацию: join и: limit. Этот метод кажется многообещающим, но, к сожалению, он вернет мне пользователей, а не комментарии, и как только я получу их обратно, у меня будет много моделей, занимающих память (для каждого Друга и Пользователя), много ненужных полей, передаваемых (все для пользователя, и все о строке имени для друзей), и мне все равно придется каким-то образом пройтись, чтобы собрать и отсортировать все комментарии в логике приложения.
  2. начиная с Комментариев и используя что-то вроде find_by_sql, но я просто не могу понять, что мне нужно вставить. Я не знаю, как у вас могла бы быть необходимая информация для передачи с этим ограничиться только просмотром комментариев, сделанных друзьями.

Редактировать : Мне сложно заставить работать решение EmFi, и я был бы признателен за любые идеи, которые кто-либо может предоставить.

Друзья - это циклическая ассоциация через таблицу соединений.

has_many :friendships
has_many :friends, 
         :through => :friendships,
         :conditions => "status = #{Friendship::FULL}"

Это ошибка, которую я получаю в соответствующей части:

ОШИБКА: столбец users.user_id не существует

: SELECT "comments".* FROM "comments"  INNER JOIN "users" ON "comments".user_id = "users".id    WHERE (("users".user_id = 1) AND ((status = 2)))

Когда я просто ввожу user.friends, и он работает, это запрос, который он выполняет:

: SELECT "users".* FROM "users" INNER JOIN "friendships" ON "users".id = "friendships".friend_id WHERE (("friendships".user_id = 1) AND ((status = 2)))

Так что, похоже, что у "до" есть два: сквозных в одном запросе.

1 Ответ

5 голосов
/ 04 марта 2010

Учитывая следующие отношения:

class User < ActiveRecord::Base
  has_many :friends           
  has_many :comments

  has_many :friends_comments, :through => :friends, :source => :comments
end

Этот оператор будет выполнять один оператор SQL. Ассоциации по существу создают именованные области для вас, которые не оцениваются до конца цепочки.

@user.friends_comments.find(:limit => 100, :order => 'created_at DESC')

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

class Comments < ActiveRecord::Base
  belongs_to :user

  #named_scope was renamed to scope in Rails 3.2. If you're working
  #if you're working in a previous version uncomment the following line.
  #named_scope :recent, :limit => 100, : order => 'created at DESC'
  scope :recent, :limit => 100, :order => 'created_at DESC'
end

Так что теперь вы можете сделать:

@user.friends_comments.recent

N.B .: Ассоциация друзей для пользователя может быть циклической через таблицу соединений, но это не важно для этого решения. Пока друзья являются рабочими ассоциациями для Пользователя, предыдущее будет работать.

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