Menu Docs

Página inicial do DocsMongoid

Mongoide 8.0

Nesta página

Esta página descreve alterações e melhorias significativas no Mongoid 8.0. A lista completa de versões está disponível no GitHub e no JIRA; consulte as versões do GitHub para obter notas de versão detalhadas e o JIRA para obter a lista completa de problemas corrigidos em cada versão, incluindo correções de bugs.

Mongoid 8 exige MongoDB 3.6 ou mais recente. Versões anteriores do servidor não são suportadas.

Mongoide 8 exige Ruby 2.6 ou mais recente. Versões anteriores do Ruby não são suportadas.

Mongoide 8 exige Rails 5.2 ou mais recente. Versões anteriores do Rails não são suportadas.

alteração interruptiva: as seguintes opções tiveram seus valores padrão alterados no Mongoid 8.0:

  • :broken_aggregables => false

  • :broken_alias_handling => false

  • :broken_and => false

  • :broken_scoping => false

  • :broken_updates => false

  • :compare_time_by_ms => true

  • :legacy_attributes => false

  • :legacy_pluck_distinct => false

  • :legacy_triple_equals => false

  • :object_id_as_json_oid => false

  • :overwrite_chained_operators => false

Consulte a opção de configuração para obter a descrição e os efeitos de cada uma dessas opções.

O Mongoid 8 introduz o sinalizador de recurso map_big_decimal_to_decimal128 , que permite que os valores atribuídos a um campo do tipo BigDecimal sejam armazenados como tipo String no banco de dados para compatibilidade com o Mongoid 7 e versões anteriores. No Mongoid 8 por padrão (com este sinalizador de recurso ativado), os valores atribuídos a campos do tipo BigDecimal são armazenados no banco de dados como tipo BSON::Decimal128. No Mongoid 7 e versões anteriores, e no Mongoid 8 com esse sinalizador de recurso desativado, os valores atribuídos a campos do tipo BigDecimal são armazenados como strings. Consulte a seção sobre Campos BigDecimal para obter mais detalhes.

alteração interruptiva: no Mongoid 8, o Mongoid padroniza o armazenamento, a recuperação e a evolução de "valores não atribuíveis". Ao tentar ler ou gravar um valor não atribuível, um nil é retornado ou gravado. Ao tentar desenvolver um valor não atribuível, o valor inserido é retornado. Consulte a seção sobre Valores não atribuíveis para obter mais detalhes.

Alguns métodos mongoize, demongoize e evolve também foram alterados para serem executados de forma consistente com o Rails e os outros métodos mongoize, demongoize e evolve . A tabela a seguir mostra as alterações na funcionalidade:

tipo de campo
Situação
Funcionalidade anterior
Nova funcionalidade
Boolean
Quando uma string não booleana é atribuída: "valor falso"
Método false
Método nil
Array/Hash
Quando um valor que não é uma array ou hash é atribuído
gerar erro InvalidValue
Método nil
definir
Quando um valor que não é um conjunto é atribuído: 1
criar NoMethodError exceção: método indefinido to_a para 1:Integer
Método nil
regexp
Ao persistir e ler um Regexp do reconhecimento de data center
devolver um BSON::Regexp::Raw
devolver um Regexp
Hora/DataHora
Ao atribuir um valor falso: :bogus
gerar NoMethodError exceção: método indefinido to_i para :bogus:Symbol
Método nil
Hora/DataHora
Ao desmongoizar um valor não temporal: "falso", Date.today
gerar NoMethodError exceção: método indefinido getlocal para "bogus":String

"bogus": return nil

Date.today: return Time/DateTime

Data
Ao atribuir ou desmongoizar um valor falso: :bogus
gerar NoMethodError exceção: método indefinido year para :bogus:Symbol
Método nil
Time/DateTime/Date
Ao desmongoizar uma string válida: "2022-07-14 14:45:51 -0400"
aumentar NoMethodError Exceção: método indefinido getlocal para "2022-07-14 14:45:51 -0400":String
devolver um Time/DateTime/Date
todos os tipos
Quando um valor não atribuível é atribuído ou desmongoizado
comportamento indefinido, ocasionalmente aumentar NoMethodError
Método nil
todos os tipos
Quando um valor não atribuível é evoluído
comportamento indefinido, ocasionalmente aumentar NoMethodError
devolver o valor inserido

Observação

Os demongoize métodos em objetos contêineres (ou seja, Hash, Array) não foram alterados para evitar erros ao modificar e salvar esses objetos. Consulte https://jira.mongodb.org/browse/MONGOID-2951 para uma discussão mais longa sobre esses bugs.

O hash attributes_before_type_cast foi alterado para funcionar mais como o ActiveRecord:

  • Na instanciação de um novo modelo (sem parâmetros), o hash attributes_before_type_cast tem o mesmo conteúdo que o hash attributes . Se os parâmetros forem passados para o inicializador, esses valores serão armazenados no hash attributes_before_type_cast antes de serem mongoized.

  • Ao atribuir um valor ao modelo, o valor mongoized (ou seja, ao atribuir '1 ' a um campo inteiro, é mongoized para 1) é armazenado no hash attributes , enquanto o valor bruto (ou seja, '1 ') é armazenado no hash attributes_before_type_cast .

  • Ao salvar, criar (ou seja, usar o método create! ) ou recarregar o modelo, o hash attributes_before_type_cast é redefinido para ter o mesmo conteúdo do hash attributes .

  • Ao ler um documento do reconhecimento de data center, o hash attributes_before_type_cast contém os atributos como eles aparecem no reconhecimento de data center, em oposição ao formato demongoized .

alteração interruptiva: Mongoide 8.0 altera a ordem de _create e _save invocação de callback para documento com associações.

Associações referenciadas (has_one e has_many):

Mongoide 8.0
Mongoid 7
Principal :before_save
Principal :before_save
Principal: em torno_save_pen
Principal: em torno_save_pen
Principal :before_create
Principal :before_create
Principal :round_create_pen
Principal :round_create_pen
Principal persistente no MongoDB
Principal persistente no MongoDB
Filho: antes_save
Principal: em torno_create_close
Filho :round_save_pen
Principal :after_create
Filho :before_create
Filho: antes_save
Filho :round_create_pen
Filho :round_save_pen
Filho :before_create

Filho :round_create_pen
Filho persistente no MongoDB
Filho persistente no MongoDB
Filho: em torno_create_close
Filho: em torno_create_close
Filho :after_create
Filho :after_create
Filho :round_save_close
Filho :round_save_close
Filho: after_save
Filho: after_save
Principal: em torno_create_close
Principal: em torno_save_close
Principal :after_create
Principal :after_save
Principal: em torno_save_close

Principal :after_save

Associações incorporadas (embeds_one e embeds_many):

Mongoide 8.0
Mongoid 7
Principal :before_save
Filho: antes_save
Principal: em torno_save_pen
Filho :round_save_pen
Principal :before_create
Filho :round_save_close
Principal :round_create_pen
Filho: after_save
Filho: antes_save
Principal :before_save
Filho :round_save_pen
Principal: em torno_save_pen
Filho :before_create
Filho :before_create
Filho :round_create_pen
Filho :round_create_pen

Filho: em torno_create_close
Filho :after_create

Principal :before_create
Principal :round_create_pen
documento persistente no MongoDB
documento persistente no MongoDB
Filho: em torno_create_close
Filho :after_create

Filho :round_save_close
Filho: after_save

Principal: em torno_create_close
Principal: em torno_create_close
Principal :after_create
Principal :after_create
Principal: em torno_save_close
Principal: em torno_save_close
Principal :after_save
Principal :after_save

Ao atualizar documento, agora é possível obter valores de atributo atualizados em after_* chamada de resposta. Isso segue o comportamento ActiveRecord/AtiveModel.

class Cat
include Mongoid::Document
field :age, type: Integer
after_save do
p self
p attribute_was(:age)
end
end
a = Cat.create!
a.age = 2
a.save!

Mongoide 8.0 saída:

#<Cat _id: 60aef1652c97a617438dc9bb, age: 2>
2

Saída Mongoid 7 :

#<Cat _id: 60aef1652c97a617438dc9bb, age: 2>
nil

Observe que em 7 attribute_was(:age) retorna o valor do atributo antigo, enquanto em 8.0 attribute_was(:age) retorna o novo valor.

Mongoide 8.0 apresenta os auxiliares *_previously_was compatíveis com o ActiveModel, bem como os auxiliares previously_new_record? e previously_persisted? compatíveis com o ActiveRecord:

class User
include Mongoid::Document
field :name, type: String
field :age, type: Integer
end
user = User.create!(name: 'Sam', age: 18)
user.previously_new_record? # => true
user.name = "Nick"
user.save!
user.name_previously_was # => "Sam"
user.age_previously_was # => 18
user.previously_new_record? # => false
user.destroy
user.previously_persisted? # => true

alteração interruptiva: o Mongoid 8 proíbe o uso de símbolos e cadeias de caracteres como tipos de campo quando esses símbolos e cadeias de caracteres não são mapeados para um tipo conhecido. Anteriormente, esse uso criaria um campo do tipo Object.

Comportamento do Mongoid 8 :

class User
include Mongoid::Document
field :name, type: :bogus
# => raises Mongoid::Errors::InvalidFieldType
end

Comportamento do Mongoid 7 :

class User
include Mongoid::Document
field :name, type: :bogus
# Equivalent to:
field :name
end

alteração interruptiva: quando any_of é invocado com várias condições, as condições agora são adicionadas ao nível superior dos critérios, o mesmo de quando any_of é invocado com uma única condição. Anteriormente, quando várias condições eram fornecidas e os critérios já tinham um operador $or , as novas condições eram adicionadas ao $or existente como uma ramificação adicional.

Mongoide 8.0 comportamento:

Band.any_of({name: 'The Rolling Stones'}, {founded: 1990}).
any_of({members: 2}, {last_tour: 1995})
# =>
# #<Mongoid::Criteria
# selector: {"$or"=>[{"name"=>"The Rolling Stones"}, {"founded"=>1990}],
# "$and"=>[{"$or"=>[{"members"=>2}, {"last_tour"=>1995}]}]}
# options: {}
# class: Band
# embedded: false>
Band.any_of({name: 'The Rolling Stones'}, {founded: 1990}).any_of({members: 2})
# =>
# #<Mongoid::Criteria
# selector: {"$or"=>[{"name"=>"The Rolling Stones"}, {"founded"=>1990}], "members"=>2}
# options: {}
# class: Band
# embedded: false>

Comportamento do Mongoid 7 :

Band.any_of({name: 'The Rolling Stones'}, {founded: 1990}).
any_of({members: 2}, {last_tour: 1995})
# =>
# #<Mongoid::Criteria
# selector: {"$or"=>[{"name"=>"The Rolling Stones"}, {"founded"=>1990},
# {"members"=>2}, {"last_tour"=>1995}]}
# options: {}
# class: Band
# embedded: false>
Band.any_of({name: 'The Rolling Stones'}, {founded: 1990}).any_of({members: 2})
# =>
# #<Mongoid::Criteria
# selector: {"$or"=>[{"name"=>"The Rolling Stones"}, {"founded"=>1990}], "members"=>2}
# options: {}
# class: Band
# embedded: false>

Mongoid 8 corrige um bug em que chamar #pluck em um Mongoid::Criteria para documentos incorporados descartava valores nulos. Esse comportamento era inconsistente com o método #pluck no ActiveSupport e com a forma como o #pluck funciona ao ler documentos do banco de dados.

Mongoide 8.0 comportamento:

class Address
include Mongoid::Document
embedded_in :mall
field :street, type: String
end
class Mall
include Mongoid::Document
embeds_many :addresses
end
mall = Mall.create!
mall.addresses.create!(street: "Elm Street")
mall.addresses.create!(street: nil)
# Pluck from embedded document criteria
mall.addresses.all.pluck(:street)
#=> ['Elm Street', nil]

Comportamento do Mongoid 7 , dada a mesma configuração:

# Pluck from embedded document criteria
mall.addresses.all.pluck(:street)
#=> ['Elm Street']

Para maior clareza, o seguinte comportamento não foi alterado de Mongoid 7 para Mongoid 8.0:

# Pluck from database
Mall.all.pluck('addresses.street')
#=> [ ['Elm Street', nil] ]
# Pluck using ActiveSupport Array#pluck
mall.addresses.pluck(:street)
#=> ['Elm Street', nil]

O método Mongoid::Criteria#geo_spacial anteriormente obsoleto foi removido no Mongoid 8. Ele foi substituído um por um por #geo_spatial que foi adicionado no Mongoid 7.2.0.

O Mongoid 8 implementa o método .tally em Mongoid#Criteria. tally usa um nome de campo como parâmetro e retorna um mapeamento dos valores para suas contagens. Para exemplo, veja o modelo abaixo:

class User
include Mongoid::Document
field :age
end

e os seguintes documento no reconhecimento de data center:

{ _id: 1, age: 21 }
{ _id: 2, age: 21 }
{ _id: 3, age: 22 }

Chamar tally no campo idade produz o seguinte:

User.tally("age")
# => { 21 => 2, 22 => 1 }

O método tally aceita a notação de ponto e os nomes alternativos de campo. Também permite registrar campos localizados.

O Mongoid 8 implementa o método .pick em Mongoid#Criteria. pick usa um ou mais nomes de campo como parâmetro e retorna os valores para esses campos de um documento. Considere o seguinte modelo:

class User
include Mongoid::Document
field :age
end

e os seguintes documento no reconhecimento de data center:

{ _id: 1, age: 21 }
{ _id: 2, age: 21 }
{ _id: 3, age: 22 }

Chamar pick no campo idade produz o seguinte:

User.pick(:age)
# => 21

Esse método não aplica uma classificação aos documentos, portanto, não necessariamente retornará os valores do primeiro documento.

O método pick aceita a notação de ponto e os nomes alternativos de campo. Também permite escolher campos localizados.

Quando recebe um bloco, sem argumentos _id , find delega para Enumerable#find. Considere o seguinte modelo:

class Band
include Mongoid::Document
field :name, type: String
end
Band.create!(name: "Depeche Mode")
Band.create!(name: "The Rolling Stones")

Chamar find com um bloco retorna o primeiro documento para o qual o bloco retorna true:

Band.find do |b|
b.name == "Depeche Mode"
end
# => #<Band _id: 62c58e383282a4cbe82bd74b, name: "Depeche Mode">

No Mongoid 8, se um documento inválido for atribuído a uma associação belongs_to e o documento base for salvo, se a associação belongs_to tiver a opção optional: false ou optional estiver desconfigurada e o sinalizador global belongs_to_required_by_default for verdadeiro, nem o documento nem o documento associado persistirão. Por exemplo, dado os modelos a seguir:

class Parent
include Mongoid::Document
has_one :child
field :name
validates :name, presence: true
end
class Child
include Mongoid::Document
belongs_to :parent, autosave: true, validate: false, optional: false
end
child = Child.new
parent = Parent.new
child.parent = parent # parent is invalid, it does not have a name
child.save

Nesse caso, o filho e o pai não serão persistidos.

Observação

Se salvar! fossem chamados, um erro de validação seria gerado.

Se opcional for falso, o filho será persistido com um array_id, mas o pai não será persistido:

child = Child.new
parent = Parent.new
child.parent = parent # parent is invalid, it does not have a name
child.save
p Child.first
# => <Child _id: 629a50b0d1327aad89d214d2, parent_id: BSON::ObjectId('629a50b0d1327aad89d214d3')>
p Parent.first
# => nil

Se você quiser que a funcionalidade de nenhum dos documentos persista no Mongoid 7 ou 8 e versões anteriores, a opção validate: true pode ser definida na associação. Se você deseja que a funcionalidade de apenas a criança seja persistente, a opção validate: false pode ser definida na associação.

No Mongoid 8, ao enviar elementos persistentes para uma associação HABTM, a associação agora será atualizada corretamente sem exigir uma recarga. Por exemplo:

class User
include Mongoid::Document
has_and_belongs_to_many :posts
end
class Post
include Mongoid::Document
has_and_belongs_to_many :users
end
user1 = User.create!
user2 = User.create!
post = user1.posts.create!
p post.users.length
# => 1
post.users << user2
p post.users.length
# => 1 in Mongoid 7, 2 in Mongoid 8
p post.reload.users.length
# => 2

Como você pode ver neste exemplo, depois de pressionar user2 para a array de usuários, o Mongoid 8 atualiza corretamente o número de elementos sem exigir uma recarga.

alteração interruptiva: no Mongoid 8, o armazenamento de uma string em um campo do tipo BSON::Binary será armazenado e retornado do banco de dados como BSON::Binary. Antes do Mongoid 8, ele era armazenado e retornado como uma string:

class Registry
include Mongoid::Document
field :data, type: BSON::Binary
end
registry = Registry.create!(data: "data!")
p registry.data
# => Mongoid 7: "data!"
# => Mongoid 8: <BSON::Binary:0x2580 type=generic data=0x6461746121...>
registry = Registry.find(registry.id)
p registry.data
# => Mongoid 7: "data!"
# => Mongoid 8: <BSON::Binary:0x2600 type=generic data=0x6461746121...>

O método Document#to_a anteriormente obsoleto foi removido no Mongoid 8.

A opção :drop_dups foi removida da macro index. Esta opção era específica do MongoDB Server 2.6 e anterior, que o Mongoid não suporta mais.

A classe de exceção Mongoid::Errors::EagerLoad anteriormente obsoleta foi removida no Mongoid 8. Não é usado pelo Mongoid desde a versão 7.1.1 quando o carregamento rápido para associações polimórficas belongs_to foi implementado.

O Mongoid 8 remove as seguintes constantes obsoletas que não se espera que tenham sido usadas fora do Mongoid:

  • Mongoid::Extensions::Date::EPOCH

  • Mongoid::Extensions::Time::EPOCH

  • Mongoid::Factory::TYPE

Os métodos Array#update_values e Hash#update_values anteriormente obsoletos foram removidos no Mongoid 8.

As opções geoHaystack e geoSearch em índices foram descontinuadas.

O suporte para a opção :id_sort nas opções #first e #last foi eliminado. Estes métodos agora exceto um limite como um argumento posicional.

O suporte para objetos de critérios de cache individuais foi descartado no Mongoid 8.

Para obter a funcionalidade de cache, ative o Mongoid Query Cache. Consulte a seção Cache de query para obter mais detalhes.

← Mongoide 8.1