2011-01-16 10 views
6

Sto usando Rails e mongoid per lavorare con mongodb.Aggiornamento semplice di dati booleani con mongdb?

Di solito in binari quando si lavora con Active: Record, si ha accesso al metodo .toggle! che ti permette semplicemente di invertire il valore di un campo booleano nel tuo db.

Purtroppo questo metodo non è disponibile per MongoDB:

user = User.first 
user.toggle!(:admin) 
NoMethodError: undefined method `toggle!' for #<User:0x00000100eee700> 

Questo è un peccato ... e abbastanza stupidamente non vedo come muoversi senza un codice complicato ...

Qualsiasi suggerimento su come ottenere lo stesso risultato in modo conciso?

Grazie,

Alex

ps: anche uno dei problemi è che quando voglio modificare il campo, si passa attraverso la convalida di nuovo ... ed è chiedere la Password che io don 't salvare nel db, quindi:

User.first.admin = !User.first.admin 

non funziona anche :(

risposta

6

il problema qui è specificamente mongoid, non MongoDB toggle! è una parte di 0., ma per fortuna non è difficile da replicare.

def toggle!(field) 
    send "#{field}=", !self.send("#{field}?") 
    save :validation => false 
end 

Aggiungo che nel modello (o aggiungerlo in un modulo, e includerlo nel modello), e le tue modelle Mongoid guadagneranno funzionalità equivalente a quello che si è abituati a in AR. Legge il valore del campo, lo inverte, lo scrive (tramite il setter, per la documentazione toggle!), quindi salva il documento, ignorando la convalida.

+0

Questo è davvero impressionante! Esattamente quello che stavo cercando ... :) Non sapevo che sintassi con invio? Non sono sicuro di cosa faccia esattamente? – Alex

+0

'send' invoca un metodo per (" invia un messaggio a ") un oggetto. '@ foo.bar (: baz)' è lo stesso di '@ foo.send (" bar ",: baz)' - poiché si specifica il nome del metodo con send, si possono passare variabili e così via. Questo è molto usato nella metaprogrammazione di Ruby. –

+0

Grazie per la spiegazione. Tuttavia, dopo aver provato a fondo, in realtà non ignora tutte le convalide. Ho un validates_length_of: password,: minimum => 6,: maximum => 40, e l'utilizzo del commutatore mi farà passare un errore sulla lunghezza della password ... :(Ma non sulle presenze valide, ecc. E salta il attr_accesible, ecc. quindi è quasi perfetto oltre alla convalida della lunghezza – Alex

0

Ok la convalida non ha funzionato a causa di un tipo, il codice dovrebbe essere:

save :validate => false (not :validation) 
0
# Get object's boolean field and toggle it 
# @param [Object] mongoid object 
# @param [String, Symbol] flag 
# @example 
# foo = User.find('123') 
# toggle_flag!(object: foo, flag: :bar) 

def toggle_flag!(object:, flag:) 
    object.update(flag => !object[flag]) 
    object.save! 
end 
+0

Spiega il tuo codice! –

+0

Fatto! Ho usato YARD per spiegare. – arkhwise