2010-12-10 43 views
3

(Toutes mes excuses à l'avance si cette question est courte sur les détails, je vais regarder les commentaires et ajouter ce que je peux)Comment mettre à jour des attributs de document Mongo imbriqués dans Rails avec Mongoid?

J'ai un modèle avec les éléments suivants:

class Product 
    include Mongoid::Document 
    include Mongoid::Timestamps 
#... 
    field :document_template, :type => Document 
    accepts_nested_attributes_for :document_template 

A l'intérieur du document_template Document, est le suivant references_many, que je veux modifier. Plus précisément, je veux changer les polices sont référencées:

class Document 
    include Mongoid::Document 
    include Mongoid::Timestamps 
#... 
    references_many :fonts, :stored_as => :array, :inverse_of => :documents 

Quelle sorte de logique et les détails que je devrais faire dans mon contrôleur et la forme pour obtenir ce fait? Veuillez commenter si vous voudriez que j'ajoute quelques-unes des choses louches que j'ai essayées; Cependant, je n'ai pas eu de chance avec aucun d'entre eux.

Voici une démonstration rapide de la question en utilisant la console de rails:

# Grab a Product and check how many fonts are in it's document_template 
ruby-1.8.7-p302 > prod = Product.find(:first) 
=> ... 
ruby-1.8.7-p302 > prod._id 
=> BSON::ObjectId('4d06af15afb3182bf5000111') 
ruby-1.8.7-p302 > prod.document_template.font_ids.count 
=> 9 

# Remove a font from the font_ids array 
ruby-1.8.7-p302 > prod.document_template.font_ids.pop 
=> BSON::ObjectId('...') # This font id was removed from font_ids 
ruby-1.8.7-p302 > prod.document_template.font_ids.count 
=> 8 

# Save the changes 
ruby-1.8.7-p302 > prod.document_template.save! 
=> true 
ruby-1.8.7-p302 > prod.save! 
=> true 

# Instantiate a new product object of that same product 
ruby-1.8.7-p302 > prod_new = Product.find(:first) 
=> ... 

# Confirm the _ids are the same 
ruby-1.8.7-p302 > prod._id == prod_new._id 
=> true 

# Check to see if the changes were persisted 
ruby-1.8.7-p302 > prod_new.document_template.font_ids.count 
=> 9 # If the changes persisted, this should be 8. 

# Grrrrr... doesn't look like it. Will the change disappear after a reload too? 

ruby-1.8.7-p302 > prod.reload 
=> ... 
ruby-1.8.7-p302 > prod.document_template.font_ids.count 
=> 9 

# ಠ_ಠ ... no dice. 

Mise à jour des objets en utilisant mongo (et non MongoId dans des rails) fonctionne comme prévu.

Kyle Banker a demandé des informations de connexion, alors le voici. Malheureusement, je ne pouvais pas trouver une meilleure source de journalisation que la sortie du serveur rails, ce qui semble suggérer que l'appel de mise à jour n'est jamais fait. Pour un certain contexte ici quelques informations du contrôleur:

def update_resource(object, attributes) 
    update_pricing_scheme(object, attributes) 
    update_document_template_fonts(object, attributes) 
end 

def update_document_template_fonts(object, attributes) 
    document_template = object.document_template 
    document_template_attributes = attributes[:document_template_attributes] 

    font_ids = document_template_attributes[:font_ids] 
    font_ids.delete("") # Removing an empty string that tags along with the font_ids. 
    font_ids.collect! { |f| BSON::ObjectId(f) } # Mongo want BSON::ObjectId 

    object.document_template.font_ids.replace font_ids 
    object.document_template.save!(:validate => false) 
    object.save!(:validate => false) 
end 

est ici la sortie du serveur rails lorsque le POST est traité:

Started GET "/admin/products/4d091b18afb3180f3d000111" for 127.0.0.1 at Wed Dec 15 13:57:28 -0600 2010 

Started POST "/admin/products/4d091b18afb3180f3d000111" for 127.0.0.1 at Wed Dec 15 13:57:49 -0600 2010 
    Processing by Admin::ProductsController#update as HTML 
    Parameters: {"commit"=>"Update Product", "authenticity_token"=>"QUW0GZw7nz83joj8ncPTtcuqHpHRtp1liq8fB7/rB5s=", "utf8"=>"✓", "id"=>"4d091b18afb3180f3d000111", "product"=>{"name"=>"Ho Ho Ho Flat Multiple Photo Modern Holiday Card", "document_template_attributes"=>{"id"=>"4d091b18afb3180f3d000112", "font_ids"=>["", "4d091b17afb3180f3d000023"]}, "description"=>"", "pricing_scheme_id"=>"4d091b17afb3180f3d00003b"}} 

development['users'].find({:_id=>BSON::ObjectId('4d091b17afb3180f3d00009b')}, {}).limit(-1) 
development['products'].find({:_id=>BSON::ObjectId('4d091b18afb3180f3d000111')}, {}).limit(-1) 
development['pricing_schemes'].find({:_id=>BSON::ObjectId('4d091b17afb3180f3d00003b')}, {}).limit(-1) 

MONGODB development['products'].update({"_id"=>BSON::ObjectId('4d091b18afb3180f3d000111')}, {"$set"=>{"updated_at"=>Wed Dec 15 19:57:50 UTC 2010}}) 

in Document#set_default_color_scheme: self.color_scheme = #<ColorScheme:0xb52f6f38> 

MONGODB development['documents'].update({"_id"=>BSON::ObjectId('4d091b18afb3180f3d000112')}, {"$set"=>{"color_scheme_name"=>"green_charcoal_black", "updated_at"=>Wed Dec 15 19:57:50 UTC 2010}}) 

Redirected to http://localhost:3000/admin/products/4d091b18afb3180f3d000111 
Completed 302 Found in 49ms 

Il ressemble à la commande MongoDB de mettre à jour les font_ids est complètement absent ...

+0

A quoi ressemble la logique de votre contrôleur? –

+0

Je dirais que ça ressemble, ummmm ... à l'anarchie puisque je n'ai pas réussi à le faire fonctionner. Je vais ajouter une version abrégée de la folie à la question. – wwilkins

+0

Cela ressemble à ceci peut être décrit dans le numéro suivant sur github: Problème Github décrivant le même problème: https://github.com/mongoid/mongoid/issuesearch?state=open&q=embedded+document#issue/357 – wwilkins

Répondre

1

Je suis parti de croire Mongoid Issue #357 cause le problème. La connexion ci-dessus suggère une mise à jour pour document_template.fonts du produit (ou font_ids) qui semble correspondre à la description du bogue.

(sidenote: Je suis un peu confus où exactement le tableau font_ids vient sinon: stored_as =>:. Tableau Je ne suis pas certain à 100% que je devrais modifier ni mais depuis font_ids est une Du point de vue des données,: field et: embeds_ * semblent être similaires dans la mesure où les informations sont incorporées dans le document parent.

+0

Goodish news tout le monde, ce problème sera probablement corrigé dans Mongoid 2.0.0.rc.1 qui devrait arriver courant janvier. – wwilkins

0

Mongoid a un arrière-plan compliqué. Par conséquent, le moyen le plus simple de diagnostiquer ceci est d'activer la journalisation du pilote. Ensuite, nous pouvons regarder les messages exacts envoyés à la base de données dans les deux cas, et nous sommes sûrs d'avoir une réponse.

Pouvez-vous attacher un enregistreur lorsque vous vous connectez à MongoDB et ensuite publier les sections pertinentes de la sortie du journal?

+0

Kyle, je crains de ne pas être trop rapide pour attacher un enregistreur à MongoDB. J'ai regardé dans mongosniff, mais j'ai eu des problèmes pour obtenir mes bibliothèques de libpcap à la bonne version. J'ai aussi essayé le mongo SetProfiling, mais je n'ai rien trouvé de remarquable, bien que cela puisse être dû au fait qu'il soit relativement nouveau pour mongo. J'ai joint des informations provenant de la sortie du serveur rails. Dans cette sortie, il semble que l'appel de mise à jour ne soit jamais effectué. Si vous avez une méthode particulière d'enregistrement mongodb, s'il vous plaît, faites le moi savoir. – wwilkins