在Mongoid中的父文档上嵌入文档的脏跟踪

时间:2010-11-23 11:06:45

标签: mongoid activemodel

我必须跟踪脏物。它与父母一起工作得很好 文档。但是当我在doc中更改嵌入或引用时,脏了 必须通过doc本身的嵌入/引用来访问。

如何跟踪父文档本身的脏问题?

2 个答案:

答案 0 :(得分:2)

我已经将mongoid扩展放在一起来解决这个问题https://github.com/versative/mongoid_relations_dirty_tracking。它只是以类似mongoid为属性的方式跟踪文档关系的变化,以便正确更新时间戳和版本。

答案 1 :(得分:1)

我不认为Mongoid自己的脏属性功能跟踪嵌入文档的更改。但是用这样的东西自己实现嵌入式文档的基本脏跟踪并不困难:

class Bar
  include Mongoid::Document
  embeds_many :foos
  attr_accessor :foos_changed
  alias_method :foos_changed?, :foos_changed
  # ...
end

class Foo
  include Mongoid::Document
  embedded_in :bar, :inverse_of => :foos
  after_save :notify_parent
  def notify_parent
    bar.foos_changed = true
  end
  # ...
end

b = Bar.create
b.foos_changed? # => nil
b.foos.create
b.foos_changed? # => true

如果您需要更多选项,例如在Bar.changes中更改嵌入式文档或跟踪特定更改,则必须覆盖changeschanged?方法,我不会这样做除非你绝对需要这些功能。

这是一种跟踪嵌入式文档中更改内容的方法:

class Bar
  include Mongoid::Document
  embeds_many :foos
  attr_writer :embedded_changes
  def embedded_changes
    @embedded_changes ||= begin
      self._children.inject({}) do |memo, child|
        memo.merge( 
         {child.collection_name => {child.id => child.changes}} 
        ) if child.changed?
      end
    end
  end

  def changes
    original_value = super
    if original_value.blank?
      embedded_changes
    else
      original_value.merge(embedded_changes)
    end
  end

  def changed?
    super || self._children.any?(&:changed?)
  end
  # ...
end

class Foo
  include Mongoid::Document
  embedded_in :bar, :inverse_of => :foos
  # ...

  field :hat
end

b = Bar.create
f = b.foos.create
b.changes   # => nil 
b.changed?  # => false 
f.hat = 1
f.changes   # => {"hat"=>[nil, "1"]} 
b.changes   # => {"foos"=>{BSON::ObjectId('4cf...')=>{"hat"=>[nil, "1"]}}}    
b.changed?  # => true