Rails 3: Как получить все сообщения, идентификаторы которых отсутствуют в данном списке? - PullRequest
6 голосов
/ 20 мая 2011

Чтобы получить все сообщения с publisher_id равным 10, 16 или 17, я делаю:

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

Как бы получить все сообщения с publisher_id , не равным до 10, 16 или 17 (т.е. все возможные идентификаторы, кроме этих трех)?

Ответы [ 7 ]

9 голосов
/ 09 апреля 2014

в рельсах 4 мы можем сделать как ниже

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

будет генерировать SQL, как показано ниже

SELECT "posts".* FROM "posts"  WHERE ("posts"."publisher_id" NOT IN (10, 16, 17))
8 голосов
/ 20 мая 2011

Просто выполните:

Post.where(["publisher_id NOT IN (?)", [10, 16, 17]])
3 голосов
/ 20 мая 2011

Не проверено, но должно быть похоже (используя gem мета):

Post.where( :id.not_eq => [10,16,17] )
0 голосов
/ 26 марта 2014

Оптимальное решение, которое я использовал:

ids = #however you get the IDS
Post.where(["id not in (?)", [0,*ids])
  • Наличие 0 означает, что в нем всегда есть один элемент (при условии, что ничто не имеет идентификатора 0)
  • IDпревращение в сплат означает, что он всегда будет массивом.
0 голосов
/ 08 октября 2013

Каждый ответ на этой странице неправильный, потому что ни один из этих ответов не учитывает ВСЕ случаи массива, Особенно массивы, которые имеют только один элемент .

Вот пример, который будет FAIL с использованием любого из так называемых решений на этой странице:

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

Единственный ответ на этой странице, который действительно находится на правильном пути и занимается этим очень важным делом,@ Тудор Константина.Но проблема в том, что он на самом деле не показал «способ» использования своей методологии для решения реального абстрактного примера вопроса, который опубликовал ОП (а не только с использованием жестко закодированных чисел).

вот мое решениединамически находить идентификаторы, не входящие в ассоциацию Activerecord, с учетом массива идентификаторов, которые нужно исключить, которые будут работать с массивом из 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!

Если этов любом случае, пожалуйста, до голосования!Если вы не уверены или не поняли один из моих комментариев, пожалуйста, дайте мне знать.

0 голосов
/ 12 октября 2012

Используя "чистый" синтаксис ActiveRecord, посыпанный Arel с помощью Rails 3, вы можете сделать что-то вроде этого:

Post.where( Post.arel_table[:publisher_id].not_in([10, 16, 17]) )
0 голосов
/ 20 мая 2011
Post.where(" id NOT IN ( 10, 16, 17) ")
...