代码之家  ›  专栏  ›  技术社区  ›  marcgg

:使用MongoDB时有一个关系问题

  •  1
  • marcgg  · 技术社区  · 15 年前

    我有一个非常简单的设置。总而言之,我正在做的是:

    class Movie
      include MongoMapper::Document
      has_one :setting
    end
    
    class Setting
      include MongoMapper::EmbeddedDocument
      belongs_to :movie
    end
    

    我要做的是以与电影相同的格式更新电影的设置其他信息。因此,我这样做:

    - form_for ['movies', @movie] do |f|
      # ...
      -f.fields_for @movie.setting do |ms|
        # ...
    

    当我收到此错误时,这不起作用:

    stack level too deep
    

    [以下文字重复一百次左右]

    /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'
    

    以下是要点:当我用电影模型中的一个键替换has-one关系时:

    key :setting, Setting
    

    …它很好用。没有堆栈错误。

    我可以放下关系,用钥匙走,但是:

    • 它不漂亮

    • 如果我尝试使用.update_属性更新movie.setting,它会删除所有其他属性。假设我更新movie.setting.key1,它将重置movie.setting.key2…这是正常的

    我在外面找不到任何有用的东西,所以任何帮助或指点都会非常感谢。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Kyle Banker    15 年前

    我很确定,has-one关系不支持作为嵌入文档。例如,这个 工作:

    class Setting
      include MongoMapper::Document
      key :movie_id, ObjectId
      belongs_to :movie
    end
    
    class Movie
      include MongoMapper::Document
      one :setting, :class => Setting
    end
    

    如果您不需要第一类设置文档(可能不需要),可以考虑使用哈希类型的键或为Mongo定义的某个自定义类型的另一个键来存储这些设置。有关示例,请参见MongoMapper测试套件中的Windowsize类。

        2
  •  0
  •   marcgg    15 年前

    我最终将设置设置为键并重载=方法:

    电影中

      def setting=(new_setting)
        super ( (self.setting.nil?)? new_setting : (self.setting.keys.merge new_setting) )
      end
    

    在设置中

      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
    

    这不是最佳的,但在有更好的方法做有一段关系之前,它会很好地工作。

    推荐文章