Грязное отслеживание внедренного документа в родительском документе в Mongoid - PullRequest
2 голосов
/ 23 ноября 2010

Мне пришлось отслеживать грязные предметы. И это прекрасно работает с родителем док. Но когда я изменяю встроенный или на который ссылается документ, грязный должен быть доступен через встроенный / на который есть ссылка в самом документе.

Как я могу отследить грязь на самом родительском документе ??

Ответы [ 2 ]

2 голосов
/ 08 октября 2013

Я собрал расширение mongoid для решения этой проблемы https://github.com/versative/mongoid_relations_dirty_tracking. Он просто отслеживает изменения в отношениях документа аналогично тому, как mongoid делает это для атрибутов, поэтому метки времени и версии обновляются правильно.

1 голос
/ 25 ноября 2010

Я не думаю, что собственная функция грязных атрибутов 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 или отслеживание конкретных изменений, вы 'Вам придется переопределить методы changes и changed?, чего бы я не сделал, если бы вам не требовались эти функции.

Вот способ отследить, что изменилось во встроенных документах:

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
...