Mongoid / Moped обновляет внедренный документ - ArgumentError - неверное количество аргументов (2 для 1)

У меня проблемы с обновлением встроенного документа в приложении Ruby / Sinatra. Я пытаюсь использовать позиционный оператор "$" в операторе обновления, чтобы выбрать правильный документ из встроенного массива. Но это приводит к ошибке "ArgumentError - неправильное количество аргументов (2 для 1)".

Простой оператор обновления с жестко заданным индексом массива работает нормально. Так, может быть, Mongoid/Moped не поддерживает оператор положения?... Хотя, как я мог видеть, похоже, что так и должно быть.

Кто-нибудь знает, каков наилучший подход? Есть ли какой-то другой способ определить индекс поддокумента, не просматривая их все, используя Ruby в моем контроллере - это план B, но, кажется, действительно ненадежный!...

Вот мои основные настройки: у меня есть "Клиенты"...

class Customer
    include Mongoid::Document
    field :customer_name, type: String

    embeds_many :contacts

    attr_accessible :customer_name
end

... со встроенными "контактами"...

class Contact
    include Mongoid::Document
    field :first_name, type: String

    attr_accessible :first_name

    embedded_in :customer
end

И в моем контроллере я получаю._ids как клиента (pk), так и конкретный внедренный документ для обновления (contact_pk):

Customer.update(
                 { 
                   "_id" => Moped::BSON::ObjectId(pk),"contacts._id" => Moped::BSON::ObjectId(contact_pk)
                 },
                 {
                   $set => {"contacts.$.first_name" => "Bob" }
                 }
                ) 

1 ответ

Решение

update метод класса на самом деле Customer.with_default_scope.update замаскированный, это означает, что update на самом деле update метод из Mongoid::Criteria и это выглядит так:

# Update the first matching document atomically.
#
# @example Update the first matching document.
#   context.update({ "$set" => { name: "Smiths" }})
#
# @param [ Hash ] attributes The new attributes for the document.
#
# @return [ nil, false ] False if no attributes were provided.
#
# @since 3.0.0
def update(attributes = nil)
  update_documents(attributes)
end

Обратите внимание, что это займет всего один attributes параметр? Это объясняет сообщение об ошибке. Предположительно вы ожидаете update работать так же, как и в оболочке MongoDB или в интерфейсе JavaScript.

Сначала вам нужно найти интересующий вас документ, а затем позвонить update на что:

Customer.where('_id' => Moped::BSON::ObjectId(pk), 'contacts._id' => Moped::BSON::ObjectId(contact_pk))
        .update($set => { 'contacts.$.first_name' => 'Bob' })
Другие вопросы по тегам