2011-09-01 79 views
1

我想知道是否有任何結合這兩個查詢沒有使用字符串在哪裏調用......?有無論如何將這些組合成一個ActiveRecord查詢?

Notification.where(:notifiable_type => "Post", :notifiable_id => post.id) 
Notification.where(:notifiable_type => "Comment", :notifiable_id => post.comments.map(&:id)) 

換句話說,我正在尋找一種方式來做到這一點而不做:

Notification.where("(notifiable_type = 'Post' AND notifiable_id = ?) OR (notifiable_type = 'Comment' AND notifiable_id in (?))", [post.id, post.comments.map(&:id)]) 

這可能嗎?

+3

你這樣做的第二種方式可以讀一點嚴厲,但說實話就好了。 – tybro0103

回答

3

您可以使用MetaWhere實現你在找什麼在乾淨和可讀的方式:

Notification.where(
    (:notifiable_type => "Post" & :notifiable_id => post.id) 
    | 
    (:notifiable_type => "Comment" & :notifiable_id => [post.comments.map(&:id)) 
) 
0

我相信這可以清理/重構,但這樣的事情可以做到這一點。

class Notification 

    scope :on_post_or_its_comments, lambda {|post| 
    on_post  = arel_table[:notifiable_type].eq('Post'). 
         and(arel_table[:notifiable_id].eq(post.id)) 
    posts_comments = arel_table[:notifiable_type].eq('Comment'). 
         and(arel_table[:notifiable_id].in(post.comments.map(&:id)) 

    where on_post.or(posts_comments) 
    } 
end 

問題是(最後我檢查)沒有辦法鏈接OR條件與ActiveRecord的Arel實現。此外,你不能|示波器(但你可以&他們)。

有人寫過的寶石可以讓你寫更多富有表現力的ActiveRecord查詢。 Metawhere是首先想到的。