Mongoid, перепутали со встроенным документом с отметками времени и версиями? - PullRequest
4 голосов
/ 11 апреля 2011

Я использую Mongoid уже около 3 месяцев, и мне удалось сделать практически все, что мне нужно, благодаря великолепному документу и ресурсам.

Но вернувшись к улучшению некоторых вещей, яСделав несколько шагов назад, я определенно много борюсь со встраиваемыми документами.

В двух словах, я пытаюсь сохранить версионность и временные метки во встроенных документах, но я не могу этого сделать.

Вот соответствующая часть моей модели:

class Content
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Paranoia

  embeds_many :localized_contents
  accepts_nested_attributes_for :localized_contents
end

class LocalizedContent
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Paranoia
  include Mongoid::Versioning

  embedded_in :content, :inverse_of => :localized_contents
end

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

Чтобы создать новый внедренный документ, я делаю следующее:

my_content = Content.find(params[:id])
my_content.localized_contents.build(params[:localized_content])
if parent.save
 #redirect, etc.
end

Это работает в том смысле, что оно успешно создает новый внедренный документ в правильном Содержании, однако поля меток времени Iоставил ноль

Теперь, если я попытаюсь обновить это localized_content:

my_content = Content.find(params[:content_id])
localized_content = my_content.localized_contents.find(params[:id])

Теперь, если я сделаю: localized_content.update_attributes(params[:localized_content]) Я получу следующую ошибку:

=> Mongoid::Errors::InvalidCollection: Access to the collection for LocalizedContent is not allowed since it is an embedded document, please access a collection from the root document.

Достаточно справедливо, затем я атомарно обновляю поля локализованного контента и сохраняю родительский:

localized_content.fieldA = "value"
localized_content.fieldB = "value"
localized_content.fieldC = "value"

my_content.save

Это работает для корректного обновления локализованного контента, но:версии не получают копию текущего localized_content, а версия не увеличивается!

Так что, как я часто читал в этих группах и на некоторых форумах в Интернете, обратные вызовы не запускаются навстроенный документ по причине производительности, так как я звоню сохранить на родительском.Опять же, достаточно справедливо, но, как и предлагалось в этих местах, я должен вместо этого вызвать save во встроенных документах ... но как!?!?!потому что каждый раз, когда я делаю, я получаю ужас:

=> Mongoid::Errors::InvalidCollection: Access to the collection for LocalizedContent is not allowed since it is an embedded document, please access a collection from the root document.

Более того, я пытался вручную отозвать обратный вызов для управления версиями на моем встроенном: localized_content.revise, и снова та же ошибка:

=> Mongoid::Errors::InvalidCollection: Access to the collection for LocalizedContent is not allowed since it is an embedded document, please access a collection from the root document.

Я схожу с ума здесь!Пожалуйста помоги.Что я делаю не так?Как следует создавать и обновлять внедренный документ, чтобы я мог вызывать (даже если мне все равно) правильные обратные вызовы для обновления отметок времени и версий?

Спасибо,

Alex

ps: я использую рельсы 3.0.3 и mongoid 2.0.1

Ответы [ 2 ]

13 голосов
/ 09 апреля 2012

На всякий случай, если этот ответ по-прежнему полезен для всех, Mongoid добавил тег, который позволяет выполнять обратные вызовы для встроенных дочерних объектов при сохранении родительского объекта.

Ваш родительский объект должен теперь выглядеть так:

class Content
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Paranoia

  embeds_many :localized_contents, cascade_callbacks: true
  accepts_nested_attributes_for :localized_contents
end

Вот и все!Теперь при сохранении родительского объекта будут выполняться обратные вызовы для дочерних объектов (и Mongoid::Timestamps достаточно умен, чтобы работать только с объектами, которые были фактически изменены).Эта информация находится в документации mongoid, в самом низу страницы встроенных документов.

4 голосов
/ 07 июня 2011

Попробуйте использовать создание вместо сборки.EmbeddedDoc.build и EmbeddedDoc.new не будут запускать никакие обратные вызовы сохранения (поскольку ничего еще не сохранено), а сохранение родительского документа не вызовет обратные вызовы встроенных детей (решение о производительности).EmbeddedDoc.create должен запускать обратные вызовы встроенных документов.

my_content = Content.find(params[:id])
puts my_content.localized_contents.create(params[:localized_content])
...