我希望有一个简单的解决方案,不涉及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>)

当前回答

如果@forums为空,接受的解决方案将失败。为了解决这个问题,我不得不这么做

Topic.find(:all, :conditions => ['forum_id not in (?)', (@forums.empty? ? '' : @forums.map(&:id))])

或者,如果使用Rails 3+:

Topic.where( 'forum_id not in (?)', (@forums.empty? ? '' : @forums.map(&:id)) ).all

其他回答

你可以尝试这样做:

Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.map(&:id)])

你可能需要执行@forums.map(&:id).join(',')。如果参数是可枚举的,我不记得Rails是否会将参数放入CSV列表。

你也可以这样做:

# in topic.rb
named_scope :not_in_forums, lambda { |forums| { :conditions => ['forum_id not in (?)', forums.select(&:id).join(',')] }

# in your controller 
Topic.not_in_forums(@forums)

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

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

借助jonnii:

Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.pluck(:id)])

使用提取而不是在元素上进行映射

通过railsconf 2012找到你不知道rails可以做的10件事

如果有人想使用两个或更多的条件,你可以这样做:

your_array = [1,2,3,4]
your_string = "SOMETHING"

YourModel.where('variable1 NOT IN (?) AND variable2=(?)',Array.wrap(your_array),your_string)

最初的帖子特别提到了使用数字id,但我来这里寻找用字符串数组做NOT IN的语法。

ActiveRecord也会很好地为你处理:

Thing.where(['state NOT IN (?)', %w{state1 state2}])