2010-09-17 10 views
16

Problema siguiente:
Necesito algo así como un ámbito vacío. Lo que significa que este ámbito es dinámico, pero responde a todos los métodos a los que suele responder un alcance. Actualmente estoy usando un poco de hack sucio. Simplemente proporciono "1 = 0" como condiciones. Encuentro esto realmente feo, ya que golpea la base de datos. Simplemente devolver una matriz vacía no funcionará, ya que el resultado debe responder a los métodos de ámbito.Ámbito vacío con Ruby on Rails

¿Existe una mejor solución existente para esto o tendré que programar esto yo mismo?

Tal vez un código de ejemplo podría ayudar a explicar lo que necesito:


class User < ActiveRecord::Base 
    named_scope :admins, :conditions => {:admin => true } 
    named_scope :none_dirty, :conditions => "1=0" # this scope is always empty 

    def none_broken 
    [] 
    end 

    def self.sum_score # okay, a bit simple, but a method like this should work! 
    total = 0 
    self.all.each do |user| 
     total += user.score 
    end 
    return total 
    end 
end 
User.admin.sum_score # the score i want to know 
User.none_drity.sum_score # works, but hits the db 
User.none_broken.sum_score # ...error, since it doesn't respond to sum_score 
+0

¿Por qué la puntuación de un conjunto vacío alguna vez sería distinta de 0? ¿Qué estás tratando de lograr aquí? – jdl

+1

Está buscando una colección vacía. – Swanand

+0

@jdl: no sería algo distinto a 0. – Baju

Respuesta

0

Lo que busca no existe. Usted podría implementar algo así mediante la aplicación de parches en el método find. Sin embargo, esto sería una exageración, así que recomiendo mantener esto a menos que sea crítico para el rendimiento.

0

que lo que necesita User.scoped({})

+0

¿No sería 'User.scoped ({})' equivalente a 'User.all'? – Swanand

+0

No es absolutamente equivalente, pero no funciona. – Baju

+0

@Swanand: no son equivalentes, 'scoped' devuelve un' ActiveRecord :: NamedScope :: Scope' vago, mientras 'User.all' devuelve una matriz. – tokland

2

Lo siento User.scoped no es lo que desea. Como se comentó, esto devuelve todo. Debería haber prestado más atención a la pregunta.

He visto where('1 = 0') sugerido anteriormente y probablemente Rails también debería almacenarlo en caché.

Además, where('1 = 0') no golpeará la base de datos hasta que haga .all, .each, o uno de los métodos de cálculo.

+1

'User.scoped' devuelve todos los usuarios, por lo que no es realmente un ámbito" vacío ". Creo que se refiere a un ámbito vacío que no devolvería ningún usuario. Tipo de equivalente a [] pero un alcance. –

0

¿Qué tal User.where(id: nil)?

O User.where(_id: nil) para mongoid.

+0

Eso todavía golpeará la base de datos y no es confiable (Es posible tener un registro con un campo de Id. Nulo, especialmente bases de datos heredadas, no Rails). – PhilT

-1

En cuanto a su código de ejemplo indica que no puede saber acerca de las consultas agregadas en SQL, que se exponen como métodos de cálculo en Rails:

User.sum(:score) le dará la suma de las puntuaciones de todos los usuarios

Tome una mirada Rieles en las guías para obtener más información:

http://guides.rubyonrails.org/active_record_querying.html#sum

+0

Ehm, no, la suma fue solo un ejemplo como se indicó anteriormente – Baju

11
User.where('false') 

devuelve un activo Registre :: Relación con cero elementos, es un alcance cadenable que no golpeará la base de datos hasta que realmente intente acceder a uno de sus elementos. Esto es similar a la solución de PhilT con ('1 = 0') pero un poco más elegante.

+0

Por otro lado, donde ('falso') no funciona con SQLite, y '1 = 0' lo hace ... –

18

Rails 4 presenta el alcance none.

Se utilizará en casos en los que tenga un método que devuelva una relación, pero hay una condición en la que no desea que se consulte la base de datos.

Si desea un alcance para devolver un uso ámbito inalterada all:

Ya no habrá una llamada a Model.all ejecutar una consulta de inmediato y devolver una matriz de registros. En Rails 4, las llamadas al Model.all equivalen a Model.scoped ahora obsoleto.Esto significa que se pueden encadenar más relaciones al Model.all y el resultado se evaluará de forma diferida.