在 Rails 中组合作用域 ActiveRecord 查询
我正在尝试为用户构建 Facebook 风格的项目提要。该提要将包含用户或用户关注的人最近所做的(关于书籍的)笔记以及其他通知,例如“您关注的用户 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
现在这工作正常,我可以从这些没有对象的数组中获取对象数组。问题。我正在努力将两个查询合并到一个按创建时间正确排序的提要中。目前我能做的最好的事情就是使用组合提要方法的用户类:
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中的数据库级别上做同样的事情?
I'm trying to build a facebook style feed of items for a user. The feed will contain recent notes (on books) made by a user or people the user follows combined with other notifications such as "user x that you follow started reading a new book". You get the idea.
So far I have a scope in my Note class which returns the notes I want:
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
and a similar scope in my Readings class which returns records built when user starts reading a book:
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
Now this works fine and I can get arrays of objects from these no problem. I'm struggling to combine the two queries into a feed which is correctly ordered by creation time. The best I can do at the moment is my user class with a combined feed method:
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
Which gets me a combined feed but strikes me as being horrendously inefficient. How can I do the equivalent at the database level in rails?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想我可能会创建一个完全独立的模型,称为 FeedItem。然后,当发生某些事件(例如创建新注释)时,您只需创建一个新的 FeedItem 记录。那么您只有一张表可供查询,并且它已经按正确的顺序排列。
I think I would probably create an entirely separate model called FeedItem. Then, when certain events occur (such as the creation of a new note), you just create a new FeedItem record. Then you only have one table to query from and it will already be in the correct order.