Как обновить вложенные атрибуты документов Mongo в Rails с помощью Mongoid? - PullRequest
3 голосов
/ 10 декабря 2010

(заранее извиняюсь, если в этом вопросе мало подробностей, я посмотрю комментарии и добавлю, что могу)

У меня есть модель со следующим:

class Product
  include Mongoid::Document
  include Mongoid::Timestamps
#...
  field :document_template, :type => Document
  accepts_nested_attributes_for :document_template

Внутри Document document_template находится следующее reference_many, которое я хочу изменить.В частности, я хочу изменить, на какие шрифты ссылаются:

class Document
  include Mongoid::Document
  include Mongoid::Timestamps
#...
  references_many :fonts, :stored_as => :array, :inverse_of => :documents

Какую логику и детали я должен иметь в своем контроллере и форме, чтобы это сделать?Пожалуйста, прокомментируйте, если вы хотите, чтобы я добавил несколько странных вещей, которые я пробовал;однако мне не повезло ни с одним из них.

Вот краткий пример проблемы с помощью консоли rails:

# Grab a Product and check how many fonts are in it's document_template
ruby-1.8.7-p302 > prod = Product.find(:first)
 => ...
ruby-1.8.7-p302 > prod._id
 => BSON::ObjectId('4d06af15afb3182bf5000111') 
ruby-1.8.7-p302 > prod.document_template.font_ids.count
 => 9

# Remove a font from the font_ids array
ruby-1.8.7-p302 > prod.document_template.font_ids.pop
 => BSON::ObjectId('...')    # This font id was removed from font_ids
ruby-1.8.7-p302 > prod.document_template.font_ids.count
 => 8

# Save the changes
ruby-1.8.7-p302 > prod.document_template.save!
 => true 
ruby-1.8.7-p302 > prod.save!
 => true 

# Instantiate a new product object of that same product
ruby-1.8.7-p302 > prod_new = Product.find(:first)
 => ...

# Confirm the _ids are the same
ruby-1.8.7-p302 > prod._id == prod_new._id
 => true 

# Check to see if the changes were persisted
ruby-1.8.7-p302 > prod_new.document_template.font_ids.count
 => 9  # If the changes persisted, this should be 8.

# Grrrrr... doesn't look like it. Will the change disappear after a reload too?

ruby-1.8.7-p302 > prod.reload
 => ...
ruby-1.8.7-p302 > prod.document_template.font_ids.count
 => 9

# ಠ_ಠ ... no dice.

Обновление объектов с использованием mongo (а не mongoid вrails) работает, как и ожидалось.

Кайл Банкер попросил некоторую информацию для регистрации, так что вот оно.К сожалению, я не смог найти лучшего источника ведения журнала, чем выходные данные с сервера rails, что, по-видимому, предполагает, что вызов обновления никогда не выполняется.Для некоторого контекста здесь есть некоторая информация от контроллера:

def update_resource(object, attributes)
  update_pricing_scheme(object, attributes)
  update_document_template_fonts(object, attributes)
end

def update_document_template_fonts(object, attributes)
  document_template = object.document_template
  document_template_attributes = attributes[:document_template_attributes]

  font_ids = document_template_attributes[:font_ids]
  font_ids.delete("") # Removing an empty string that tags along with the font_ids.
  font_ids.collect! { |f| BSON::ObjectId(f) } # Mongo want BSON::ObjectId

  object.document_template.font_ids.replace font_ids
  object.document_template.save!(:validate => false)
  object.save!(:validate => false)
end

Вот выходные данные сервера rails при обработке POST:

Started GET "/admin/products/4d091b18afb3180f3d000111" for 127.0.0.1 at Wed Dec 15 13:57:28 -0600 2010

Started POST "/admin/products/4d091b18afb3180f3d000111" for 127.0.0.1 at Wed Dec 15 13:57:49 -0600 2010
  Processing by Admin::ProductsController#update as HTML
  Parameters: {"commit"=>"Update Product", "authenticity_token"=>"QUW0GZw7nz83joj8ncPTtcuqHpHRtp1liq8fB7/rB5s=", "utf8"=>"✓", "id"=>"4d091b18afb3180f3d000111", "product"=>{"name"=>"Ho Ho Ho Flat Multiple Photo Modern Holiday Card", "document_template_attributes"=>{"id"=>"4d091b18afb3180f3d000112", "font_ids"=>["", "4d091b17afb3180f3d000023"]}, "description"=>"", "pricing_scheme_id"=>"4d091b17afb3180f3d00003b"}}

development['users'].find({:_id=>BSON::ObjectId('4d091b17afb3180f3d00009b')}, {}).limit(-1)
development['products'].find({:_id=>BSON::ObjectId('4d091b18afb3180f3d000111')}, {}).limit(-1)
development['pricing_schemes'].find({:_id=>BSON::ObjectId('4d091b17afb3180f3d00003b')}, {}).limit(-1)

MONGODB development['products'].update({"_id"=>BSON::ObjectId('4d091b18afb3180f3d000111')}, {"$set"=>{"updated_at"=>Wed Dec 15 19:57:50 UTC 2010}})

in Document#set_default_color_scheme: self.color_scheme = #<ColorScheme:0xb52f6f38>

MONGODB development['documents'].update({"_id"=>BSON::ObjectId('4d091b18afb3180f3d000112')}, {"$set"=>{"color_scheme_name"=>"green_charcoal_black", "updated_at"=>Wed Dec 15 19:57:50 UTC 2010}})

Redirected to http://localhost:3000/admin/products/4d091b18afb3180f3d000111
Completed 302 Found in 49ms

Это похоже на команду MONGODB для обновленияfont_ids полностью отсутствует ...

Ответы [ 2 ]

1 голос
/ 15 декабря 2010

Я не верю, что Mongoid Issue # 357 вызывает проблему. Приведенные выше записи предполагают, что обновление для документа document_template.fonts (или font_ids), которое, кажется, соответствует описанию ошибки.

(sidenote: Я немного запутался, откуда берется именно массив font_ids, если не массив: store_as =>:. Я не уверен на 100%, что мне следует изменить либо , но font_ids - массив, шрифты - Mongoid :: Criteria, путь наименьшего сопротивления - font_ids.)

С точки зрения данных: field и: embeds_ * кажутся похожими в том, что информация встроена в родительский документ.

0 голосов
/ 15 декабря 2010

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

Можете ли вы подключить регистратор при подключении к MongoDB и затем опубликовать соответствующие разделы вывода журнала?

...