2016-03-31 28 views
13

Sto usando Mongoid in un progetto Rails (entrambi 4.0.x) e ho un documento con un campo hash che memorizza alcuni dati senza schema.impostazione valori campo hash mongoid

class Thing 
    field :name, type: String 
    field :mass, type: Integer 
    field :info, type: Hash 
end 

Con questa impostazione, posso interrogare per le cose, diciamo, che hanno una chiave :endDate in questo modo:

Thing.where("info.endDate"=>{'$exists'=>true}) 

E questo è tutto bello e pratico. L'utilizzo di un campo hash per questo campo :info è piacevole perché ciò che voglio archiviare non ha uno schema fisso e varia da una cosa all'altra.

Ok, ma non è possibile utilizzare la stessa sintassi del punto sulle coppie chiave/valorenell'hash :info. [1]

thing.set("info.endDate"=>Time.now) 

solleva un errore di Mongoid::Errors::UnknownAttribute.

Mi dice che dovrei includere Mongoid::Attributes::Dynamic nel mio modello per fare questo, ma che non sembra giusto per me. The point of the hash field type sembra essere per consentire di lavorare con dati che non hanno uno schema fisso. Non sembra che dovrei includere uno speciale modulo "attributi dinamici" per usare i campi hash.

Così adesso, sto aggiornando i valori utilizzando regolare vecchi [] sintassi, e quindi chiamando save sul modello, in questo modo:

thing.info[:endDate] = Time.now 
thing.save 

Ma un sacco di tempo accade che sarebbe stato più bello a solo $set il valore. C'è qualche altra sintassi per l'impostazione dei valori dei campi hash? Mi sbaglio sul precedente messaggio di errore e gli attributi dinamici sono errati? Per ora sono bloccato ad aggiornare in due passaggi i campi hash?

[1] devo ammettere che di recente sono migrato da mongomapper e quindi le mie aspettative su questa sintassi sono in parte impostate dall'aver potuto farlo precedentemente in mongomapper.

+1

penso che embeds_one, che sarà definita come Mongoid :: :: attributi dinamici, lavorerà per voi (mai provato questo approccio) –

+2

I don non voglio un documento incorporato Voglio un campo hash perché i dati che sto memorizzando variano da documento a documento. E mongoid mi dà un modo per interrogare su coppie di chiavi/valore specifiche all'interno di quell'hash. Mi piacerebbe essere in grado di aggiornare le coppie chiave/valore in quell'Hash con la stessa facilità, usando $ set. – Bee

+0

Non dovrebbe essere '.set (: info => {: endDate => Time.now})" È stato un po 'di tempo da quando ho lavorato con MongoDB però. –

risposta

9

La cosa con il campo di hash è, può essere dinamico tanto quanto si desidera. Pertanto, per evitare di inquinare lo schema del DB con campi indesiderati causati da bug nel codice, questa funzionalità è disabilitata per impostazione predefinita.

No, non sei bloccato con gli aggiornamenti in 2 passaggi per i tuoi hash!

[], [] = sono le scorciatoie per read_attribute() e write_attribute() e dovrebbero essere utilizzate se non si include Mongoid::Attributes::Dynamic. Se si tenta di utilizzare $set senza abilitare gli attributi dinamici, si otterrà un errore senza metodo poiché non vede gli attributi dinamici come attributi definiti.

Se leggerai la fonte di Mongoid::Attributes::Dynamic, allora troverai che questo è necessario per aggiungere la funzionalità degli attributi dinamici.

per aggiornare i valori includendo Mongoid::Attributes::Dynamic è necessario seguire questi passaggi:

thing = Thing.first 
thing.set("info.endDate" => Time.now) 
thing.reload # This will update the current variable 

In caso contrario, se avete bisogno si può facilmente saltare questo e fare l'aggiornamento del valore con il metodo 2-step

spero questo getta un po 'di luce sulla tua domanda.

Fonte:

Rails mongoid dynamic fields - no method error

Dynamic attributes with Rails and Mongoid

+0

Sono ancora insoddisfatto di questa risposta. La documentazione sui campi dinamici sembra riferirsi all'aggiunta dinamica dei campi al documento. Non sembra che impostare una coppia chiave/valore all'interno di un campo Hash dichiarato sia ciò a cui si riferiscono quando parlano di campi dinamici. A che serve un tipo di dati hash in cui non è possibile aggiungere coppie chiave/valore arbitrarie? E infatti posso aggiungere valori arbitrari all'Hash, semplicemente non usando $ set, apparentemente. Ma forse sto solo discutendo del design di mongoid qui. Non lo so. – Bee

+1

@Bee So che sembra frustrante non essere in grado di utilizzare '$ set' solo quando lo si desidera nei campi Hash. Come ho spiegato nella mia risposta, hanno disabilitato la funzione per usare '$ set' perché i valori possono essere dinamici e se ci sono alcuni errori nel codice, può portare a campi non intenzionali. Ma quando stai usando [], [] = sei abbastanza sicuro di quali valori stai usando. Questo è solo come è stato progettato. Ma possiamo abilitare '$ set' per i campi hash includendo quel modulo e dicendo a Mongoid che siamo abbastanza sicuri del codice che abbiamo codificato. Pensa dal punto di vista dell'autore e sembra giusto. –

+1

Eccellente !! Funziona perfettamente: D –

1

Penso che si passi il parametro in modo errato. Sostituire il simbolo freccia con virgola

È possibile modificare a questo e funzionerà

thing.set("info.endDate", Time.now) 
+0

Grazie! Ma questa è la sintassi per i set Mongoid 3.x. A partire da Mongoid 4.x passarono a passare un hash di coppie campo/valore da impostare. – Bee

+0

Sì @Bee, in realtà sto usando mongoid 3.x nel mio progetto corrente. e sì mongoid 4.x, imposta gli argomenti come coppia chiave-valore. Grazie per la tua risposta – Sukanta