在rails中组合范围的activerecord查询

时间:2011-03-21 21:35:59

标签: ruby-on-rails ruby-on-rails-3 activerecord

我正在尝试为用户构建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中的数据库级别执行等效操作?

1 个答案:

答案 0 :(得分:2)

我想我可能会创建一个名为FeedItem的完全独立的模型。然后,当某些事件发生时(例如创建新笔记),您只需创建一个新的FeedItem记录。然后你只有一个表可以查询,它已经按正确的顺序排列。