¿Cómo devolver una relación ActiveRecord vacía?
Si tengo un ámbito con una lambda y toma un argumento, dependiendo del valor del argumento, podría saber que no habrá ninguna coincidencia, pero aún quiero devolver una relación, no un array vacío:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : [] }
Lo que realmente quiero es un método "none", lo opuesto a "all", que devuelva una relación que todavía se puede encadenar, pero que resulte en un cortocircuito de la consulta.
9 answers
Ahora hay un mecanismo "correcto" en Rails 4:
>> Model.none
=> #<ActiveRecord::Relation []>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 02:25:45
Una solución más portátil que no requiere una columna "id"y no asume que no habrá una fila con un id de 0:
scope :none, where("1 = 0")
Todavía estoy buscando una manera más "correcta".
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-16 04:12:59
Puede agregar un ámbito llamado"none":
scope :none, where(:id => nil).where("id IS NOT ?", nil)
Eso te dará un ActiveRecord::Relation vacío
También puedes añadirlo a ActiveRecord:: Base en un inicializador (si quieres):
class ActiveRecord::Base
def self.none
where(arel_table[:id].eq(nil).and(arel_table[:id].not_eq(nil)))
end
end
Muchas maneras de obtener algo como esto, pero ciertamente no es lo mejor para mantener en una base de código. He usado el scope: none al refactorizar y encontrar que necesito garantizar una relación vacía ActiveRecord:: por un corto tiempo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-21 06:49:21
Viene en Raíles 4
En Rails 4, se devolverá un ActiveRecord::NullRelation
encadenable desde llamadas como Post.none
.
Ni él, ni los métodos encadenados, generarán consultas a la base de datos.
Según los comentarios:
El ActiveRecord::NullRelation devuelto hereda de Relation and implements the Null Object pattern. Es un objeto con comportamiento null definido y siempre devuelve una matriz vacía de registros sin quering la base de datos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-23 19:28:45
scope :none, limit(0)
Es una solución peligrosa porque su alcance podría estar encadenado.
Usuario.ninguno.primero
Devolverá el primer usuario. Es más seguro usar
scope :none, where('1 = 0')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-12 16:00:47
Creo que prefiero la forma en que esto se ve a las otras opciones:
scope :none, limit(0)
Que conduce a algo como esto:
scope :users, lambda { |ids| ids.present? ? where("user_id IN (?)", ids) : limit(0) }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-22 13:59:31
Use ámbito de aplicación:
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)) }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-04 05:33:47
También hay variantes, pero todas estas están haciendo una solicitud a db
where('false')
where('null')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-17 12:34:21
Es posible y eso es:
scope :for_users, lambda { |users| users.any? ? where("user_id IN (?)", users.map(&:id).join(',')) : User.none }
Http://apidock.com/rails/v4.0.2/ActiveRecord/QueryMethods/none
Corrígeme si me equivoco.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-13 14:03:50