Solo para actualizar esto, ya que parece que mucha gente viene a esto, si está utilizando Rails 4, vea las respuestas de Trung Lê` y VinniVidiVicci.
Topic.where.not(forum_id:@forums.map(&:id))
Topic.where(published:true).where.not(forum_id:@forums.map(&:id))
Espero que haya una solución fácil que no implique find_by_sql
, si no, supongo que tendrá que funcionar.
Encontré este artículo que hace referencia a esto:
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
que es lo mismo que
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
Me pregunto si hay una manera de hacer NOT IN
eso, como:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
ruby-on-rails
rails-activerecord
Toby Joiner
fuente
fuente
Person.all(:name.not => ['bob','rick','steve'])
Respuestas:
Rieles 4+:
Carriles 3:
¿Dónde
actions
está una matriz con:[1,2,3,4,5]
fuente
Topic.where('id NOT IN (?)', (actions.empty? ? '', actions)
. Todavía se rompería en cero, pero creo que la matriz que pasa generalmente es generada por un filtro que regresará[]
al menos y nunca será cero. Recomiendo echar un vistazo a Squeel, un DSL además de Active Record. Entonces podría hacer:Topic.where{id.not_in actions}
nulo / vacío / o de otra manera..empty?
para.blank?
y que son nulas a pruebaPara su información, en Rails 4, puede usar la
not
sintaxis:fuente
Puedes probar algo como:
Es posible que deba hacer
@forums.map(&:id).join(',')
. No recuerdo si Rails incluirá el argumento en una lista CSV si es enumerable.También puedes hacer esto:
fuente
Usando Arel:
o, si se prefiere:
y como los carriles 4 en:
Tenga en cuenta que eventualmente no desea que forum_ids sea la lista de identificadores, sino una subconsulta, si es así, debe hacer algo como esto antes de obtener los temas:
de esta manera obtienes todo en una sola consulta: algo así como:
También tenga en cuenta que eventualmente no desea hacer esto, sino una unión, lo que podría ser más eficiente.
fuente
EXPLAIN
!Para ampliar la respuesta @Trung Lê, en Rails 4 puede hacer lo siguiente:
Y podrías ir un paso más allá. Si primero necesita filtrar solo los Temas publicados y luego filtrar los identificadores que no desea, puede hacer esto:
¡Rails 4 lo hace mucho más fácil!
fuente
La solución aceptada falla si
@forums
está vacía. Para solucionar esto tuve que hacerO, si usa Rails 3+:
fuente
La mayoría de las respuestas anteriores deberían ser suficientes, pero si está haciendo muchas más de tales combinaciones predicadas y complejas, consulte Squeel . Podrás hacer algo como:
fuente
Es posible que desee echar un vistazo al complemento meta_where de Ernie Miller. Su declaración SQL:
... podría expresarse así:
Ryan Bates de Railscasts creó un bonito screencast explicando MetaWhere .
No estoy seguro de si esto es lo que está buscando, pero a mi parecer, ciertamente se ve mejor que una consulta SQL incrustada.
fuente
La publicación original menciona específicamente el uso de ID numéricos, pero vine aquí buscando la sintaxis para hacer un NOT IN con una serie de cadenas.
ActiveRecord también lo manejará muy bien para usted:
fuente
¿Se pueden resolver estos identificadores de foro de forma pragmática? por ejemplo, ¿puedes encontrar estos foros de alguna manera? Si ese es el caso, deberías hacer algo como
Lo cual sería más eficiente que hacer un SQL
not in
fuente
De esta manera, se optimiza la legibilidad, pero no es tan eficiente en términos de consultas a la base de datos:
fuente
Puede usar sql en sus condiciones:
fuente
Piggybacking fuera de jonnii:
usando punteo en lugar de mapear sobre los elementos
encontrado a través de railsconf 2012 10 cosas que no sabías que rails podía hacer
fuente
Cuando consulta una matriz en blanco, agregue "<< 0" a la matriz en el bloque where para que no devuelva "NULL" y rompa la consulta.
Si las acciones podrían ser una matriz vacía o en blanco.
fuente
Topic.where("id NOT IN (?)", actions.presence || [0])
Aquí hay una consulta más compleja "no en", usando una subconsulta en rails 4 usando squeel. Por supuesto, muy lento en comparación con el sql equivalente, pero bueno, funciona.
Los primeros 2 métodos en el alcance son otros ámbitos que declaran los alias cavtl1 y tl1. << es el operador no en chirrido.
Espero que esto ayude a alguien.
fuente