2010-09-17 19 views
16

Following Problema:
Ho bisogno di qualcosa come un ambito vuoto. Questo significa che questo scope è emtpy, ma risponde a tutti i metodi a cui solitamente risponde un ambito. Attualmente sto usando un piccolo trucco sporco. Fornisco semplicemente "1 = 0" come condizioni. Lo trovo davvero brutto, dal momento che colpisce il database. La semplice restituzione di un array vuoto non funzionerà, poiché il risultato deve rispondere ai metodi dell'ambito.Scope vuoto con Ruby on Rails

Esiste una soluzione esistente migliore per questo o dovrò codificarlo da solo?

Forse qualche esempio di codice potrebbe contribuire a spiegare che cosa ho bisogno:


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

Perché il punteggio di un set vuoto deve mai essere diverso da 0? Cosa stai cercando di realizzare qui? – jdl

+1

Stai cercando una collezione vuota. – Swanand

+0

@jdl: non sarebbe diverso da 0. – Baju

risposta

0

La cosa che stai cercando non esiste. È possibile implementare qualcosa di simile da monky patching del metodo find. Tuttavia, questo sarebbe eccessivo, quindi raccomando di tenerlo a meno che non sia critico per le prestazioni.

0

io cosa che devi User.scoped({})

+0

Non sarebbe 'User.scoped ({})' equivalente a 'User.all'? – Swanand

+0

Non è assolutamente equivalente, ma non funziona. – Baju

+0

@Swanand: non sono equivalenti, 'scoped' restituisce un pigro' ActiveRecord :: NamedScope :: Scope' mentre 'User.all' restituisce una matrice. – tokland

2

Spiacente User.scoped non è quello che vuoi. Come ha commentato questo restituisce tutto. Dovrebbe aver prestato più attenzione alla domanda.

Ho visto where('1 = 0') suggerito prima e Rails dovrebbe probabilmente memorizzarlo nella cache.

Inoltre, where('1 = 0') non colpirà il database finché non si esegue .all, .each o uno dei metodi di calcolo.

+1

'User.scoped' restituisce tutti gli utenti, quindi non è realmente un ambito" vuoto ". Penso che intenda un ambito vuoto che non restituirebbe alcun utente. Una sorta di equivalente a [] ma un ambito. –

0

Che ne dici di User.where(id: nil)?

oppure User.where(_id: nil) per mongolo.

+0

Ciò continuerà a colpire il database e non è affidabile (è possibile avere un record con un campo id null in particolare legacy, database non Rails). – PhilT

-1

Guardando il tuo codice di esempio indica che non si può sapere sulle query aggregate in SQL che sono esposti come metodi di calcolo in Rails:

User.sum(:score) vi darà la somma dei punteggi di tutti gli utenti

Date un'occhiata a Rails Guide per ulteriori informazioni:

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

+0

Ehm, no, la somma era solo un esempio come indicato sopra – Baju

11
User.where('false') 

restituisce un attivo Record :: Relazione con elementi zero, che è un ambito capace di catena che non colpirà il database finché non proverai ad accedere ad uno dei suoi elementi. Questo è simile alla soluzione di PhilT con ('1 = 0') ma un po 'più elegante.

+0

D'altra parte dove ('false') non funziona con SQLite, e '1 = 0' fa ... –

18

Rails 4 introduce lo scope none.

È da utilizzare nei casi in cui si dispone di un metodo che restituisce una relazione, ma esiste una condizione in cui non si desidera interrogare il database.

Se si desidera un ambito per restituire un uso ambito inalterato all:

non sarà più una chiamata a Model.all eseguire immediatamente una query e restituisce un array di record. In Rails 4, le chiamate a Model.all equivalgono a ora deprecate Model.scoped.Ciò significa che più relazioni possono essere concatenate a Model.all e il risultato sarà valutato pigramente.