我正在尝试为用户构建Facebook样式的项目Feed。该Feed将包含由用户或用户跟随的人组成的最近笔记(在书上)以及其他通知,例如“您跟随的用户x开始阅读新书”。你明白了。
到目前为止,我的Note类中有一个范围,它返回我想要的笔记:
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
和我的Readings类中的类似范围,它返回用户开始阅读书籍时构建的记录:
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
现在这个工作正常,我可以从这些中获取对象数组没问题。我正在努力将两个查询组合成一个按创建时间正确排序的Feed。我现在能做的最好的事情是我的用户类使用了一个组合的feed方法:
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
这让我得到了一个综合的饲料,但让我感到非常低效。如何在rails中的数据库级别执行等效操作?
答案 0 :(得分:2)
我想我可能会创建一个名为FeedItem的完全独立的模型。然后,当某些事件发生时(例如创建新笔记),您只需创建一个新的FeedItem记录。然后你只有一个表可以查询,它已经按正确的顺序排列。