Я пытаюсь создать фид в стиле Facebook для пользователя. Фид будет содержать последние заметки (о книгах), сделанные пользователем или людьми, за которыми пользователь следует, в сочетании с другими уведомлениями, такими как «пользователь x, за которым вы следите, начал читать новую книгу». Вы поняли идею.
Пока у меня есть класс в моем классе заметок, который возвращает нужные мне заметки:
class Note < ActiveRecord::Base
scope :from_users_followed_by, lambda { |user| followed_by user }
def self.followed_by(user)
followed_ids = %(SELECT followed_id FROM relationships WHERE follower_id = :user_id)
where("user_id IN (#{followed_ids}) OR user_id = :user_id", { :user_id => user })
end
end
и аналогичная область в моем классе «Чтения», которая возвращает записи, созданные, когда пользователь начинает читать книгу:
class Reading < ActiveRecord::Base
scope :from_users_followed_by, lambda { |user| followed_by(user) }
def self.followed_by(user)
# is this not at risk of sql injection??
followed_ids = %(SELECT followed_id FROM relationships WHERE follower_id = :user_id)
# return readings where user_id IN (an array of user_ids that the user follows)
where("reader_id IN (#{followed_ids}) OR reader_id = :user_id", { :user_id => user })
end
end
Теперь это работает нормально, и я могу получить массивы объектов из них без проблем. Я изо всех сил пытаюсь объединить два запроса в канал, который правильно упорядочен по времени создания. Лучшее, что я могу сделать на данный момент, - это мой класс пользователя с комбинированным методом подачи:
class User < ActiveRecord::Base
def combined_feed
feed = Note.from_users_followed_by(self) | Reading.from_users_followed_by(self)
feed.sort! do |a, b|
a.created_at <=> b.created_at
end
feed.reverse
end
end
Что дает мне комбинированный корм, но кажется мне ужасно неэффективным. Как я могу сделать эквивалент на уровне базы данных в рельсах?