ruby-on-rails - llaves - relaciones en rails




¿Cómo devolver una relación vacía de ActiveRecord? (6)

Si tengo un ámbito con un lambda y toma un argumento, dependiendo del valor del argumento, puedo saber que no habrá coincidencias, pero aún quiero devolver una relación, no una matriz vacía:

scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }

Lo que realmente quiero es un método "ninguno", lo opuesto a "todos", que devuelve una relación que aún puede ser encadenada, pero que resulta en una consulta cortocircuitada.


Viniendo en rieles 4

En Rails 4, se devolverá un ActiveRecord::NullRelation de llamadas como Post.none .

Ni esto, ni los métodos encadenados, generarán consultas a la base de datos.

Según los comentarios:

El ActiveRecord :: NullRelation devuelto se hereda de la relación e implementa el patrón de objeto nulo. Es un objeto con un comportamiento nulo definido y siempre devuelve una matriz de registros vacía sin consultar la base de datos.

Consulte el código fuente .


Ahora hay un mecanismo "correcto" en Rails 4:

>> Model.none 
=> #<ActiveRecord::Relation []>


Puedes agregar un alcance llamado "ninguno":

scope :none, where(:id => nil).where("id IS NOT ?", nil)

Eso te dará un ActiveRecord vacío :: Relación

También puede agregarlo a ActiveRecord :: Base en un inicializador (si lo desea):

class ActiveRecord::Base
 def self.none
   where(arel_table[:id].eq(nil).and(arel_table[:id].not_eq(nil)))
 end
end

Hay muchas maneras de obtener algo como esto, pero ciertamente no es lo mejor para mantener en una base de código. He utilizado el alcance: ninguno al refactorizar y encontrar que necesito garantizar un ActiveRecord :: Relation vacío por un corto tiempo.


Una solución más portátil que no requiere una columna "id" y no asume que no habrá una fila con una id de 0:

scope :none, where("1 = 0")

Todavía estoy buscando una forma más "correcta".


Utilizar ámbito:

scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : scoped }

Pero, también puedes simplificar tu código con:

scope :for_users, lambda { |users| where(:user_id => users.map(&:id)) if users.any? }

Si desea un resultado vacío, use esto (elimine la condición if):

scope :for_users, lambda { |users| where(:user_id => users.map(&:id)) }




relation