: Problema de relación has_one cuando se utiliza MongoDB
-
22-09-2019 - |
Pregunta
Tengo una configuración bastante simple. Para resumir, esto es lo que estoy haciendo:
class Movie
include MongoMapper::Document
has_one :setting
end
class Setting
include MongoMapper::EmbeddedDocument
belongs_to :movie
end
Lo que quiero hacer es actualizar la configuración de una película en la misma forma que la película otra información. Para ello yo que:
- form_for ['movies', @movie] do |f|
# ...
-f.fields_for @movie.setting do |ms|
# ...
Esto no funciona como se me sale este error:
stack level too deep
[abajo texto se repite una vez centenar de]
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations/one_proxy.rb:46:in `find_target'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations/proxy.rb:98:in `load_target'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations/proxy.rb:88:in `method_missing'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations/one_proxy.rb:56:in `target_class'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations/one_proxy.rb:46:in `find_target'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations/proxy.rb:98:in `load_target'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations/one_proxy.rb:17:in `replace'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/associations.rb:39:in `setting='
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/embedded_document.rb:185:in `send'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/embedded_document.rb:185:in `initialize'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/embedded_document.rb:177:in `each'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/embedded_document.rb:177:in `initialize'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/dirty.rb:42:in `initialize'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/embedded_document.rb:91:in `new'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/embedded_document.rb:91:in `initialize_doc'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/document.rb:316:in `find_one'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/document.rb:321:in `find_one!'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/document.rb:88:in `find!'
/Users/marc/.gem/ruby/1.8/gems/mongo_mapper-0.6.10/lib/mongo_mapper/document.rb:96:in `find'
/Users/marc/Code/mycompany/dontreadthat/sources/app/controllers/application_controller.rb:53:in `set_page_title'
Aquí está la trampa: cuando se sustituye la relación has_one por una clave en el modelo de la película:
key :setting, Setting
... funciona bien. No hay error de pila.
Yo sólo podría bajar la relación e ir con la llave pero:
-
No es bonito
-
Si trato de actualización movie.setting usando .update_attributes cae todos los demás atributos. Digamos que la actualización movie.setting.key1, se restablecerá movie.setting.key2 ... lo cual es normal
No se puede encontrar algo útil por ahí, por lo que cualquier ayuda o sugerencias serán bienvenidos.
Solución 2
terminé de regulación La regulación como una llave y la sobrecarga del método =:
en la película
def setting=(new_setting)
super ( (self.setting.nil?)? new_setting : (self.setting.keys.merge new_setting) )
end
y en el ajuste
def keys
keys_hash = {}
self.attributes.each do |attribute|
keys_hash.merge!( {attribute[0].to_s => attribute[1].to_s}) unless attribute[0].to_s == "_id"
end
return keys_hash
end
No es óptimo, pero que va a trabajar bien hasta que hay una mejor manera de hacer las relaciones has_one.
Otros consejos
estoy bastante seguro de que las relaciones has_one no se admiten como documentos incrustados. Así, por ejemplo, este hace de trabajo:
class Setting
include MongoMapper::Document
key :movie_id, ObjectId
belongs_to :movie
end
class Movie
include MongoMapper::Document
one :setting, :class => Setting
end
Si no desea que el documento de configuración de primera clase, que probablemente no es necesario, es posible considerar el almacenamiento de estas funciones usando una llave de tipo hash u otra tecla de algún tipo personalizado que haya definido para Mongo. Consulte la clase WindowSize en el banco de pruebas MongoMapper para un ejemplo.