我希望有一个简单的解决方案,不涉及find_by_sql,如果没有,那么我想这将不得不工作。

我发现这篇文章引用了这个:

Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })

哪个是一样的

SELECT * FROM topics WHERE forum_id IN (<@forum ids>)

我想知道是否有一种方法可以不这样做,比如:

SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)

当前回答

上面的大多数答案应该足以满足您的需求,但如果您正在进行更多此类谓词和复杂组合,请查看Squeel。你可以这样做:

Topic.where{{forum_id.not_in => @forums.map(&:id)}}
Topic.where{forum_id.not_in @forums.map(&:id)} 
Topic.where{forum_id << @forums.map(&:id)}

其他回答

上面的大多数答案应该足以满足您的需求,但如果您正在进行更多此类谓词和复杂组合,请查看Squeel。你可以这样做:

Topic.where{{forum_id.not_in => @forums.map(&:id)}}
Topic.where{forum_id.not_in @forums.map(&:id)} 
Topic.where{forum_id << @forums.map(&:id)}

要扩展@Trung Lê答案,在Rails 4中您可以执行以下操作:

Topic.where.not(forum_id:@forums.map(&:id))

你可以更进一步。 如果你需要先过滤发布的主题,然后过滤掉你不想要的id,你可以这样做:

Topic.where(published:true).where.not(forum_id:@forums.map(&:id))

Rails 4让它变得更简单!

使用服装:

topics=Topic.arel_table
Topic.where(topics[:forum_id].not_in(@forum_ids))

或者,如果喜欢的话:

topics=Topic.arel_table
Topic.where(topics[:forum_id].in(@forum_ids).not)

由于rails在:

topics=Topic.arel_table
Topic.where.not(topics[:forum_id].in(@forum_ids))

请注意,最终你不希望forum_ids是ids列表,而是一个子查询,如果是这样,那么你应该在获得主题之前做这样的事情:

@forum_ids = Forum.where(/*whatever conditions are desirable*/).select(:id)

通过这种方式,您可以在一个查询中获得所有内容:类似于:

select * from topic 
where forum_id in (select id 
                   from forum 
                   where /*whatever conditions are desirable*/)

还要注意,最终您并不想这样做,而是想要一个连接——这可能更有效。

你可以在你的条件下使用sql:

Topic.find(:all, :conditions => [ "forum_id NOT IN (?)", @forums.map(&:id)])

当你查询一个空数组时,在where块中添加"<< 0"到数组中,这样它就不会返回"NULL"并中断查询。

Topic.where('id not in (?)',actions << 0)

If actions可以是空数组或空数组。