ruby on rails - code - Rieles donde se condiciona utilizando NOT NULL
rails code (5)
Con Rails 4 es fácil:
Foo.includes(:bar).where.not(bars: {id: nil})
Véase también: http://guides.rubyonrails.org/active_record_querying.html#not-conditions
Usando el estilo de los rieles 3, ¿cómo escribiría lo contrario de:
Foo.includes(:bar).where(:bars=>{:id=>nil})
Quiero encontrar donde ID no es nula. Lo intenté:
Foo.includes(:bar).where(:bars=>{:id=>!nil}).to_sql
Pero eso vuelve:
=> "SELECT /"foos/".* FROM /"foos/" WHERE (/"bars/"./"id/" = 1)"
Eso definitivamente no es lo que necesito, y casi parece un error en ARel.
La forma canónica de hacer esto con Rails 3:
Foo.includes(:bar).where("bars.id IS NOT NULL")
ActiveRecord 4.0 y superior agrega where.not
para que pueda hacer esto:
Foo.includes(:bar).where.not(''bars.id'' => nil)
Foo.includes(:bar).where.not(bars: { id: nil })
Cuando trabajo con ámbitos entre tablas, prefiero aprovechar la merge
para poder usar los ámbitos existentes con mayor facilidad.
Foo.includes(:bar).merge(Bar.where.not(id: nil))
Además, dado que include no siempre elige una estrategia de unión, también debe usar references
aquí, de lo contrario puede terminar con un SQL no válido.
Foo.includes(:bar)
.references(:bar)
.merge(Bar.where.not(id: nil))
No es un error en ARel, es un error en tu lógica.
Lo que quieres aquí es:
Foo.includes(:bar).where(Bar.arel_table[:id].not_eq(nil))
No estoy seguro de esto es útil, pero esto es lo que me funcionó en Rails 4
Foo.where.not(bar: nil)
Para Rails4:
Entonces, lo que estás buscando es una unión interna, por lo que deberías usar el predicado de uniones:
Foo.joins(:bar)
Select * from Foo Inner Join Bars ...
Pero, para el registro, si desea una condición "NOT NULL" simplemente use el no predicado:
Foo.includes(:bar).where.not(bars: {id: nil})
Select * from Foo Left Outer Join Bars on .. WHERE bars.id IS NOT NULL
Tenga en cuenta que esta sintaxis informa de una desaprobación (habla de un fragmento de código SQL de cadena, pero supongo que la condición de hash se cambia a cadena en el analizador), así que asegúrese de agregar las referencias al final:
Foo.includes(:bar).where.not(bars: {id: nil}).references(:bar)
ADVERTENCIA DE DEPRECACIÓN: Parece que está ansioso por cargar tablas (una de: ....) a las que se hace referencia en un fragmento de código SQL de cadena. Por ejemplo:
Post.includes(:comments).where("comments.title = ''foo''")
Actualmente, Active Record reconoce la tabla en la cadena y sabe UNIR la tabla de comentarios a la consulta, en lugar de cargar comentarios en una consulta separada. Sin embargo, hacer esto sin escribir un analizador de SQL completo es inherentemente defectuoso. Como no queremos escribir un analizador de SQL, estamos eliminando esta funcionalidad. A partir de ahora, debe indicar explícitamente el Registro activo cuando haga referencia a una tabla desde una cadena:
Post.includes(:comments).where("comments.title = ''foo''").references(:comments)