2012-05-24 103 views
21

我有一个标签源和一个好友源。 我想结合这两个并构建最终的“全部”饲料。如何将两个示波器组合在一起或者是

对于朋友订阅:

class Post < ActiveRecord::Base 
    scope :friendfeed, lambda{|x| followed_by} 

    def self.followed_by(user) 
    where("user_id IN (?) OR user_id = ?", user.watched_ids, user.id) 
    end 
end 

对于标签饲料:

class Post < ActiveRecord::Base 
    scope :tagfeed, lambda{|x| infatuated_with} 

    def self.infatuated_with(user) 
    joins(:attachments).where("attachments.tag_id IN (?)", user.tags).select("DISTINCT pages.*") 
    end 
end 

而且我会叫这样的事情从控制器(我使用雷创业板分页):

@tag_feed = Post.tagfeed(current_user).page(params[:page]).per(21) 
@friend_feed = Post.friendfeed(current_user).page(params[:page]).per(21) 

现在我想拥有一个通用饲料,但我迷路了。范围是为了缩小范围,但在这种情况下,我试图执行OR操作。这样做的东西像

@mother_of_all_feed = @tag_feed + @friend_feed 

是多余的,我就无法控制出现在单页上的帖子的数量。我怎么能这样做呢?谢谢!

顺便说一句,标签为我协会成立这样的:

class Post < ActiveRecord::Base 
    has_many :attachments 
    has_many :tags, :through => :attachments 
end 

class Tag < ActiveRecord::Base 
    has_many :attachments 
    has_many :posts, :through => :attachments 
end 

class Attachment < ActiveRecord::Base 
    belongs_to :tag 
    belongs_to :post 
end 

回答

4

回答我的问题。我想我想出了一个办法。

where("pages.id IN (?) OR pages.id IN (?)", 
    Page.where(
     "user_id IN (?) OR user_id = ?", 
     user.watched_ids, user.id 
), 
    Page 
    .joins(:attachments) 
    .where("attachments.tag_id IN (?)", user.tags) 
    .select("DISTINCT pages.*") 
) 

它似乎到目前为止,希望这是它!

+6

你对它的性能满意吗?看起来你在这里得到4-5个查询。看起来你有两个选择:编写原始的SQL查询或使用我最喜欢的gem squeel。它允许执行OR并支持导致嵌套SQL查询的'in'功能。看看:https://github.com/ernie/squeel。我尝试了几次“做广告”,像这样:http://stackoverflow.com/a/10551561/1322562,但只有少数人喜欢它。我想知道为什么。通过使用squeel,您可以重复使用您的作用域并在纯Ruby中构建复杂的查询,如:通过单一(!!!)SQL查询生成Product.where {(id.in Product.ruby)|(id.in Product.rails)}' ! – jdoe

+0

不满意,但我只是原型,所以没关系。我会看看squeel。谢谢! – Vlad

17

对此功能(https://github.com/rails/rails/pull/9052)有一个滑轨拉取请求(https://github.com/rails/rails/pull/9052),但同时,有人创建了一个猴子修补程序,您可以在初始化程序中包含这些修补程序,以允许您在一个查询中使用范围和where子句,但仍然给你一个ActiveRecord::Relation

https://gist.github.com/j-mcnally/250eaaceef234dd8971b

就这样,你能或者你的范围这样

Post.tagfeed(current_user).or.friendfeed(current_user) 

或写一个新的范围

scope :mother_of_all_feed, lambda{|user| tagfeed(user).or.friendfeed(user)} 
+3

一些建设性的批评将受到任何人低估这一点的赞赏。它解决了这个问题,并且不会生成嵌套查询。 – keithepley

+3

OR将被添加到Rails 5.0中:https://github.com/rails/rails/pull/16052 –

+1

是的,OR已经被添加到Rails 5中的ActiveRecord :: Relation#或者' /nithinbekal.com/posts/rails-5-features/ – leviathan