无论如何将它们组合成一个ActiveRecord查询?

时间:2011-09-01 21:56:38

标签: ruby-on-rails activerecord

我想知道是否还有将这两个查询在没有的情况下使用where调用中的字符串进行组合...?

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)])

有可能吗?

2 个答案:

答案 0 :(得分:3)

您可以使用MetaWhere以清晰易读的方式实现您的目标:

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

答案 1 :(得分: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

问题是(最后我检查过)没有办法用ActiveRecord的Arel实现链接OR条件。此外,你不能|范围(但你可以&)。

人们编写的宝石可以让你写出更具表现力的ActiveRecord查询。首先想到的是Metawhere