Rails 3:如何获取所有帖子哪个ID不在给定列表中?

时间:2011-05-20 04:00:00

标签: ruby-on-rails ruby-on-rails-3 activerecord active-relation

要获取publisher_id等于10,16或17的所有帖子,我会这样做:

Post.where(:publisher_id => [10, 16, 17])

如何将publisher_id 不等于的所有帖子都添加到10,16或17(即除了这三个以外的所有可能的ID)?

7 个答案:

答案 0 :(得分:9)

在rails 4中,我们可以像下面这样做

Post.where.not(:publisher_id => [10, 16, 17])

它将生成如下的SQL

SELECT "posts".* FROM "posts"  WHERE ("posts"."publisher_id" NOT IN (10, 16, 17))

答案 1 :(得分:8)

只需执行:

Post.where(["publisher_id NOT IN (?)", [10, 16, 17]])

答案 2 :(得分:3)

未经测试,但应该像(使用metawhere gem):

Post.where( :id.not_eq => [10,16,17] )

答案 3 :(得分:0)

使用" pure"使用Rails 3在Arel上使用ActiveRecord语法,您可以执行以下操作:

Post.where( Post.arel_table[:publisher_id].not_in([10, 16, 17]) )

答案 4 :(得分:0)

此页面上的每个答案都是错误的,因为这些答案都没有处理所有数组的情况,特别是只有一个元素的数组

以下是使用此页面上任何“所谓”解决方案失败的示例:

@ids = [1]
Post.where("publisher_id NOT IN (?)", @ids)
#ERROR
Post.where("publisher_id NOT IN (?)", [4])
#ERROR
#...etc

#ALSO
@ids = []
Post.where("publisher_id NOT IN (?)", @ids)
#ERROR
Post.where("publisher_id NOT IN (?)", [])
#ERROR
#...etc

#The problem here is that when the array only has one item, only that element is 
#returned, NOT an array, like we had specified

#Part of the sql that is generated looks like:
#...WHERE (publisher_id NOT IN 166)

#It should be:
#...WHERE (publisher_id NOT IN (166))

这页上唯一真正走在正确轨道上并且处理这个非常重要案例的答案是@Tudor Constantin's。但问题是他实际上没有表现出使用他的方法来解决OP发布的真实抽象示例问题的“方式”(不仅仅是使用硬编码的数字)。

这是我的解决方案,在给定要排除的id数组的情况下动态查找不在Activerecord关联中的id,这将使用n个元素的数组(...包括n = 1和n = 0)

@ids = [166]
@attribute = "publisher_id"
@predicate = "NOT IN"
@ids = "(" + @ids.join(",") + ")"
if @ids == "()"
  #Empty array, just set @ids, @attribute, and @predicate to nil
  @ids = @attribute = @predicate = nil
end

#Finally, make the query
Post.where( [@attribute, @predicate, @ids].join(" ") ) 

#Part of the sql that is generated looks like:
#...WHERE (publisher_id NOT IN (166))
#CORRECT!

#If we had set @ids = []     (empty array)
#Then the if statement sets everything to nil, and then
#rails removes the blank "  " space in the where clause automatically and does
#the query as if all records should be returned, which
#logically makes sense!

如果这对你有帮助,请投票!如果您感到困惑或不理解我的评论,请告诉我。

答案 5 :(得分:0)

我用过的整洁解决方案:

ids = #however you get the IDS
Post.where(["id not in (?)", [0,*ids])
  • 0的存在意味着它总是有一个元素(假设没有ID为0)
  • ID成为splat意味着它将永远是一个数组。

答案 6 :(得分:-2)

Post.where(" id NOT IN ( 10, 16, 17) ")